现在Python 3.10已经发布了,在指示参数或返回值可能是可选的(即可以是
None
)时是否有任何偏好。那么首选什么:
选项1:
def f(parameter: Optional[int]) -> Optional[str]:
选项2:
def f(parameter: int | None) -> str | None:
另外,
Type | None
和None | Type
之间有什么偏好吗?
PEP 604 在规范部分涵盖了这些主题。
现有的
和typing.Union
语法应该是等效的。|
int | str == typing.Union[int, str]
联盟中项目的顺序与平等无关。
(int | str) == (str | int) (int | str | float) == typing.Union[str, float, int]
可选值应等同于新的联合语法
None | t == typing.Optional[t]
由于 @jonrsharpe 评论,
Union
和 Optional
并未弃用,因此 Union
和 |
语法是可以接受的。
Łukasz Langa 在与 Python 3.10 版本相关的 YouTube 直播中回复称,对于 Python 3.10+,
Type | None
优于 Optional[Type]
。
我个人会继续选择选项 2。
另外,只是想添加这个以提高认识,但 Python 3.7+ 可以使用
__future__
导入来支持此语法,如下所示。这种类型的检查是一样的;实际上,我从我目前正在使用的 Pycharm 的最新发行说明中得到了提示。
from __future__ import annotations
def f(parameter: int | None) -> str | None:
...
这完全是我的观点,但我认为虽然它们相当于类型检查器,但它们向人类读者表达了非常不同的意图。所以它们不可互换。
如果您要声明默认值,请将其输入为
def foo(bar: Optional[int] = None)
,它声明了您不必传递参数的显式意图。
但是,如果您没有默认值,则可以声明它
def foo(bar: int | None)
,它声明这是一个必需参数,其中 None
是有效参数值之一。
大多数时候,你想做前者,所以大多数时候你仍然应该使用
Optional[int]
;但在某些情况下,要求调用者显式传递 None 可能是可取的。
第二个原因是写
def foo(bar: int | None = None)
看起来很难看,并且与重复的None
混淆。
非权威,但我希望
Optional
何时
None
)None
呼叫者通过会很不寻常虽然我希望在
时使用一些
Union
或
|
None
None
也是一个有效值请参阅相关建议:使用类型提示时如何向函数添加默认参数?
在返回封闭类的类型的特定情况下,您仍然需要使用
Optional
即使是python3.10+。从 python3.11.6 开始仍然如此。
例如:
# temp.py
class A:
def __init__(self):
print("init")
def test(self) -> "A" | None:
pass
尝试运行
temp.py
会遇到 TypeError
:
$ python3.11 temp.py
Traceback (most recent call last):
File "/Users/vietthan/Documents/temp.py", line 1, in <module>
class A:
File "/Users/vietthan/Documents/temp.py", line 5, in A
def test(self) -> "A" | None:
~~~~^~~~~~
TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'
我检查了 mypy、black、ruff,它们都没有发现这个错误。