随着类型提示的发展,Python 添加了更简单、更简洁的语法。但是您仍然需要了解旧表单,因为 Mypy 在报告类型时使用它们。
联合类型
联合类型结合了几种类型,表示一个值可以是这些类型中的任何一种。PEP 484 引入了类型提示并定义Union
为表示联合类型,允许您编写:
from typing import Union
age: Union[int, float]
后来,PEP 604添加了|联合语法的运算符。这允许您跳过导入Optional并改为编写:
age: int | float
此功能是在 Python 3.10 中添加的。但是你可以从 Python 3.7 开始使用它,如果你使用 Mypy 0.800+并且使用from future import annotations.
可选类型
可选类型基本上是类型和None. 该值要么存在,要么存在None。
写这个的第一种方法是Union:
from typing import Union
name: Union[str, None]
由于可选类型很常见,原始类型提示 PEP 484 添加了一个快捷方式,typing.Optional:
from typing import Optional
name: Optional[str]
但是从 PEP 604 开始,最好使用简洁的联合语法:
name: str | None
(如果海尼克·施拉瓦克(Hynek Schlawack)喝醉了合适的人,这甚至可能str?在未来成为现实。)
列表和其他内置容器
首次引入类型提示时,它们尽可能避免中断。为了避免更改常见类型,该typing模块为内置类型引入了容器类型。例如,您可以用 表示 a listof ints typing.List:
from typing import List
years: List[int]
PEP 585后来将该功能合并回内置类型。这允许您编写:
years: list[int]
这适用于许多类型:
- 其他内置容器类型:dict、tuple、set和frozenset
- 基础类型,type
- 模块中的collections.abc许多抽象基类,如Callable,Iterable和Generator
- 模块中的collections类型,例如defaultdict和deque
- 模块中的正则re表达式类型:Pattern和Match
您可以在 PEP中查看完整列表。
这些更改是在 Python 3.9 中添加的。但同样,如果您使用 Mypy 0.800+并使用from __future__ import annotations.
pyupgrade 可以帮助你采用新的语法
pyupgrade工具会自动重写代码以使用最新的 Python 语法。它支持采用上述所有新语法,包括更改导入。查看我之前的帖子了解更多详情。
Mypy 使用旧语法报告
在编写代码时使用最新最好的语法非常好。但是当 Mypy 报告类型时,它通常仍然使用旧语法(至少从 Mypy 0.982 开始),因此您仍然需要知道如何阅读它。
以这个组合示例为例,用于reveal_type()报告类型:
age: int | float
name: str | None
years: list[int]
reveal_type(age)
reveal_type(name)
reveal_type(years)
Mypy 说:
$ mypy example.py
example.py:5: note: Revealed type is "Union[builtins.int, builtins.float]"
example.py:6: note: Revealed type is "Union[builtins.str, None]"
example.py:7: note: Revealed type is "builtins.list[builtins.int]"
Success: no issues found in 1 source file
注意区别:
- 联合类型使用Union代替|
- 内置类型都以builtins
- list保留其新语法,而不是使用typing.List
Mypy 还可以报告Optional,例如对于这种错误分配:
name: str | None = 123
…它说:
$ mypy example.py
example.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "Optional[str]")
Found 1 error in 1 file (checked 1 source file)
因此,至少现在,您需要了解旧语法才能理解 Mypy 的输出。
我希望看到 Mypy 更新为更新、更短形式的报告类型。我找不到具体的问题,但我猜现在没有更新,因为 Mypy 支持较旧的 Python 版本(不使用时__future__.annotations)。我还看到 PEP 604 联合语法有一些挥之不去的边缘情况。