当您使关键字参数接受None
时,mypy 将隐式地使该参数成为类型(Optional[Blah]
如果它还没有的话)。您可以通过将reveal_type(...)
函数添加到代码并运行来看到这一点mypy
:
def foo(value: int = None) -> None:
print(value, type(value))
reveal_type(foo)
foo(None)
输出将是:
test.py:4: error: Revealed type is 'def (value: Union[builtins.int, None] =)'
(但请务必reveal_type
在实际运行代码之前删除,因为该函数实际上在运行时并不存在——它只是 mypy 的特殊情况以帮助调试。)
这种行为的存在主要是因为它有助于降低函数签名的噪音。毕竟,如果value
在某些时候允许为 None,显然它必须同时接受 int 和 None。在这种情况下,为什么不只是推断类型是Optional[int]
(相当于Union[int, None]
,顺便说一句)所以用户不需要重复相同的信息两次?
当然,并不是每个人都喜欢这种行为:有些人更喜欢更明确。在这种情况下,使用标志运行 mypy --no-implicit-optional
。这将产生以下输出:
test.py:1: error: Incompatible default for argument "value" (default has type "None", argument has type "int")
test.py:4: error: Revealed type is 'def (value: builtins.int =)'
test.py:5: error: Argument 1 to "foo" has incompatible type "None"; expected "int"
当然,您需要更改函数签名。
如果您想以其他各种方式提高 mypy 的严格性,请尝试传递--strict
标志。这将自动启用--no-implicit-optional
和其他几个严格标志。有关更多详细信息,请运行mypy --help
.