默认参数会覆盖 mypy 的类型提示吗? [英] Does a default parameters overwrite type hints for mypy?
问题描述
以下代码按预期被 mypy
拒绝:
def foo(value: int) ->没有任何:打印(值,类型(值))foo(无)
输出:
错误:参数 1 为foo";具有不兼容的类型无";预期的int"
但是引入了一个None
的默认参数后,就没有错误了:
def foo(value: int=None) ->没有任何:打印(值,类型(值))foo(无)
如果我们从 int<更改
value
,我希望 mypy
只允许 None
(作为参数和默认值)/code> 到 Optional[int]
,但似乎不需要.为什么?
当您让关键字参数接受 None
时,mypy 将隐式地使该参数的类型为 Optional[Blah]
如果还没有.您可以通过将 reveal_type(...)
函数添加到您的代码并运行 mypy
来亲眼看到这一点:
def foo(value: int = None) ->没有任何:打印(值,类型(值))揭示类型(富)foo(无)
输出将是:
test.py:4: error: Revealed type is 'def (value: Union[builtins.int, None] =)'
(请务必在实际运行代码之前删除 reveal_type
,因为该函数在运行时实际上并不存在——它只是 mypy 的特殊情况以帮助调试.)>
这种行为的存在主要是因为它有助于减少函数签名的噪音.毕竟,如果 value
在某个时候允许为 None,显然它必须同时接受整数和 None.在这种情况下,为什么不只是将类型推断为 Optional[None]
(相当于 Union[int, None]
,顺便说一句),这样用户就不会需要重复两次相同的信息?
当然,并非所有人都喜欢这种行为:有些人更喜欢表现得更直白.在这种情况下,使用 --no-implicit-optional
标志运行 mypy.这将产生以下输出:
test.py:1: 错误:参数value"的默认值不兼容(默认类型为None",参数类型为int")test.py:4: 错误: 显示类型是def (value: builtins.int =)"test.py:5: 错误:foo"的参数 1 具有不兼容的类型无";预期的int"
当然,您需要更改函数签名.
如果您想以其他各种方式提高 mypy 的严格性,请尝试传入 --strict
标志.这将自动启用 --no-implicit-optional
和其他几个严格标志.有关更多详细信息,请运行 mypy --help
.
The following code is rejected by mypy
as expected:
def foo(value: int) -> None:
print(value, type(value))
foo(None)
output:
error: Argument 1 to "foo" has incompatible type "None"; expected "int"
But after introducing a default parameter of None
, there is no error anymore:
def foo(value: int=None) -> None:
print(value, type(value))
foo(None)
I would expect mypy
to only allow None
(as argument and as the default) if we change value
from int
to Optional[int]
, but it seems like this is not needed. Why?
When you make a keyword argument accept None
, mypy will implicitly make that argument be of type Optional[Blah]
if it isn't already. You can see this for yourself by adding the reveal_type(...)
function to your code and running mypy
:
def foo(value: int = None) -> None:
print(value, type(value))
reveal_type(foo)
foo(None)
The output would be:
test.py:4: error: Revealed type is 'def (value: Union[builtins.int, None] =)'
(Be sure to delete reveal_type
before actually running your code though, since the function doesn't actually exist at runtime -- it's just special-cased by mypy to help with debugging.)
This behavior exists mostly because it helps makes the signatures of functions less noisy. After all, if value
, at some point, is allowed to be None, clearly it must accept both ints and None. In that case, why not just infer the type to be Optional[None]
(which is equivalent to Union[int, None]
, btw) so the user doesn't need to repeat the same info twice?
Of course, not everybody likes this behavior: some people prefer being more explicit. In that case, run mypy with the --no-implicit-optional
flag. That will produce the following output:
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"
You'd need to change your function signature though, of course.
If you'd like to raise the strictness of mypy in various other ways, try passing in the --strict
flag. That will automatically enable --no-implicit-optional
and several other strictness flags. For more details, run mypy --help
.
这篇关于默认参数会覆盖 mypy 的类型提示吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!