空列表的正确类型提示是什么?

lem*_*sss 12 python typing type-hinting python-3.x

什么是正确的类型提示x = []

我的 PyCharm 编辑器中的类型检查器将此标记为错误:

labelframes: List[ttk.LabelFrame] = []
Run Code Online (Sandbox Code Playgroud)

'Optional' 不是一个选项,如:

labelframes: List[Optional[ttk.LabelFrame]] = []
Run Code Online (Sandbox Code Playgroud)

因为文档typing.Optional说明这相当于:

labelframes: List[Union[ttk.LabelFrame, None]] = []
Run Code Online (Sandbox Code Playgroud)

并且[None]不是[]

我应该提到 PyCharm 也不喜欢这样:

labelframes: List[Union[ttk.LabelFrame, None]] = [None]
Run Code Online (Sandbox Code Playgroud)

无论我尝试什么类型的提示。PyCharm 将其标记为错误,“预期在此处返回我的类型提示,但没有返回”,因此我尝试了:

labelframes: Optional[List[ttk.LabelFrame, None]] = []
Run Code Online (Sandbox Code Playgroud)

那没有用。

我知道 PEP 526 有许多遵循以下模式的示例:

x: List[str] = []
Run Code Online (Sandbox Code Playgroud)

Jim*_*ard 6

看看 PEP 484,特别是关于类型注释(变量注释的前身)的部分,这确实看起来像是 PyCharm 的检查器的一个错误。

引自 PEP:

在非存根代码中,有一个类似的特例:

from typing import IO

stream = None  # type: IO[str]
Run Code Online (Sandbox Code Playgroud)

类型检查器不应对此抱怨(尽管值None与给定类型不匹配),也不应将推断类型更改为Optional[...](尽管规则对默认值为 None 的带注释的参数执行此操作)。这里的假设是其他代码将确保变量被赋予正确类型的值,并且所有使用都可以假设变量具有给定类型。

因此,以类似的方式,类型检查器(就像mypy当前所做的那样)不应该抱怨您提供的初始化值与注释不严格匹配的事实。


Law*_*tre 6

首先,我们为一个空列表编写示例代码,并使用 mypy.txt 进行检查。

from typing_extensions import reveal_type

l = []
reveal_type(l)
Run Code Online (Sandbox Code Playgroud)

现在让我们在 shell 中运行它,如下所示。

$ mypy test.py

test.py:4: error: Need type annotation for "l" (hint: "l: List[<type>] = ...")
test.py:6: note: Revealed type is "builtins.list[Any]"
Found 1 error in 1 file (checked 1 source file)
Run Code Online (Sandbox Code Playgroud)

现在请注意第二行,因为它表示类型是List[Any]

让我们进行更改并重新运行

from typing import Any, List
from typing_extensions import reveal_type

l : List[Any] = []

reveal_type(l)
Run Code Online (Sandbox Code Playgroud)

现在运行 mypy。

$ mypy test.py

test.py:6: note: Revealed type is "builtins.list[Any]"
Success: no issues found in 1 source file
Run Code Online (Sandbox Code Playgroud)