"sys.version_info" 的类型是什么?
What is the type of "sys.version_info"?
如何向以下函数添加类型注释?
import sys
def f(info):
return info.major
f(sys.version_info)
使用pyannotate
建议应该是:
import sys
def f(info):
# type: (sys.version_info) -> int
return info.major
f(sys.version_info)
然而 mypy
抱怨:
$ mypy test.py
test.py:10: error: Variable "sys.version_info" is not valid as a type
test.py:12: error: sys.version_info? has no attribute "major"```
sys.version_info
的类型好像是它自己:
>>> import sys
>>> type(sys.version_info)
<class 'sys.version_info'>
它看起来像一个 NamedTuple
,但如果它被这样注释:
from typing import NamedTuple
VersionInfo = NamedTuple(
'sys.version_info', [
('major', int),
('minor', int),
('micro', int),
('releaselevel', str),
('serial', int)
]
)
import sys
def f(info):
# type: (VersionInfo) -> int
return info.major
f(sys.version_info)
mypy
检查仍然失败:
$ mypy test.py
test.py:25: error: Argument 1 to "f" has incompatible type "_version_info"; expected "sys.version_info@9"
为了找到某些标准库函数的类型,您应该查看 Typeshed,标准库的类型提示存储库 + select 第 3 方模块。
在这种情况下,我们可以看到 sys.version_info
是 annotated as being of type sys._version_info
,这是一个伪造的,仅合成类型 class subclass 是 Tuple[int, int, int, str, int]
.
您也可以通过 运行 mypy 针对以下程序自行验证:
import sys
reveal_type(sys.version_info)
这会产生以下输出——请注意最后的回退:
Revealed type is 'Tuple[builtins.int, builtins.int, builtins.int, builtins.str, builtins.int, fallback=sys._version_info]'
因此,要注释您的函数,您有多种选择。首先,您可以使用这种仅进行类型检查的 class——您只需要确保在运行时永远不会导入它 it/reference。
如果您使用的是类型注释语法(例如 # type: (sys._version_info) -> int
),这个问题已经为您解决了。毕竟,注释中的代码片段永远不会在运行时进行评估。
但是如果你想使用 Python-3 样式类型注释,你可以这样做:
from __future__ import annotations
import sys
def f(info: sys._version_info) -> int:
return info.major
f(sys.version_info)
__future__
导入基本上使上面的程序等同于下面的程序——所有类型提示都被视为字符串,因此不需要在运行时求值:
import sys
def f(info: "sys._version_info") -> int:
return info.major
f(sys.version_info)
或者,如果您想显式导入没有 sys
模块命名空间的类型,您也可以这样做:
from __future__ import annotations
from typing import TYPE_CHECKING
import sys
# Doing just 'if False:' also works
if TYPE_CHECKING:
from sys import _version_info as VersionInfo
def f(info: VersionInfo) -> int:
return info.major
f(sys.version_info)
如何向以下函数添加类型注释?
import sys
def f(info):
return info.major
f(sys.version_info)
使用pyannotate
建议应该是:
import sys
def f(info):
# type: (sys.version_info) -> int
return info.major
f(sys.version_info)
然而 mypy
抱怨:
$ mypy test.py
test.py:10: error: Variable "sys.version_info" is not valid as a type
test.py:12: error: sys.version_info? has no attribute "major"```
sys.version_info
的类型好像是它自己:
>>> import sys
>>> type(sys.version_info)
<class 'sys.version_info'>
它看起来像一个 NamedTuple
,但如果它被这样注释:
from typing import NamedTuple
VersionInfo = NamedTuple(
'sys.version_info', [
('major', int),
('minor', int),
('micro', int),
('releaselevel', str),
('serial', int)
]
)
import sys
def f(info):
# type: (VersionInfo) -> int
return info.major
f(sys.version_info)
mypy
检查仍然失败:
$ mypy test.py
test.py:25: error: Argument 1 to "f" has incompatible type "_version_info"; expected "sys.version_info@9"
为了找到某些标准库函数的类型,您应该查看 Typeshed,标准库的类型提示存储库 + select 第 3 方模块。
在这种情况下,我们可以看到 sys.version_info
是 annotated as being of type sys._version_info
,这是一个伪造的,仅合成类型 class subclass 是 Tuple[int, int, int, str, int]
.
您也可以通过 运行 mypy 针对以下程序自行验证:
import sys
reveal_type(sys.version_info)
这会产生以下输出——请注意最后的回退:
Revealed type is 'Tuple[builtins.int, builtins.int, builtins.int, builtins.str, builtins.int, fallback=sys._version_info]'
因此,要注释您的函数,您有多种选择。首先,您可以使用这种仅进行类型检查的 class——您只需要确保在运行时永远不会导入它 it/reference。
如果您使用的是类型注释语法(例如 # type: (sys._version_info) -> int
),这个问题已经为您解决了。毕竟,注释中的代码片段永远不会在运行时进行评估。
但是如果你想使用 Python-3 样式类型注释,你可以这样做:
from __future__ import annotations
import sys
def f(info: sys._version_info) -> int:
return info.major
f(sys.version_info)
__future__
导入基本上使上面的程序等同于下面的程序——所有类型提示都被视为字符串,因此不需要在运行时求值:
import sys
def f(info: "sys._version_info") -> int:
return info.major
f(sys.version_info)
或者,如果您想显式导入没有 sys
模块命名空间的类型,您也可以这样做:
from __future__ import annotations
from typing import TYPE_CHECKING
import sys
# Doing just 'if False:' also works
if TYPE_CHECKING:
from sys import _version_info as VersionInfo
def f(info: VersionInfo) -> int:
return info.major
f(sys.version_info)