我注意到 mypy 在进入 lambda 范围时会忘记类型信息。下面用一个小例子来解释一下:
from typing import Optional, Callable
def wrapper(x: Callable[[], None]):
x()
def foo(a: int):
print(str(a))
a: Optional[int] = 0
if a is None:
exit()
wrapper(lambda: foo(a))
Mypy 提示此代码片段出现错误:“foo”的参数 1 具有不兼容的类型“None”;预期为“int”。
但是,我们之前已经检查过 a 不是
(没有包装器),它确实可以工作。
我正在使用 python 3.6.10 和 mypy 0.740。None
。这是令人惊讶的奇怪,因为如果我们直接调用 foo(a)
这是预期的行为吗?如果是这样,您将如何正确输入此内容?
谢谢!
最佳答案
这不是由于 lambda
,而是由于 a
是一个闭包。简而言之,即使特定代码无法触发错误路径,该函数在技术上也是错误的。
与修复函数中的闭包的类似问题一样,强制在定义时评估名称可以提供有效的类型:
wrapper(lambda a=a: foo(a))
请注意mypy cannot properly infer lambda
types ,因此像这样使用 lambda
仍然会导致错误 Cannot infer type of lambda
。
考虑完全等效的命名函数:
def l() -> None:
# reveal_type(a) -> Union[builtins.int, None]
return foo(a)
请注意,a:Optional[int]
在这里是可见的,而不是在 a is None
保护之后减少的 a: int
。所以问题不是来自 lambda
,而是来自 def
。
问题的根源在于 l
和 lambda
都对 a
的所有值进行封闭。即使在定义 l
/lambda
之前 a: None
已被拒绝,稍后重置 a
也是有效的.
a: Optional[int]
if a is None: exit()
def l() -> None:
# reveal_type(a) -> Union[builtins.int, None]
return foo(a)
a = None
关于python - mypy lambda 可选检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64610100/