我注意到 mypy 在进入 lambda 范围时会忘记类型信息。下面用一个小例子来解释一下:from typing import Optional, Callabledef wrapper(x: Callable[[], None]): x()def foo(a: int): print(str(a))a: Optional[int] = 0if a is None: exit()wrapper(lambda: foo(a))Mypy 抱怨这个片段错误:Argument 1 to "foo" has incompatible type "None"; expected "int"。然而,我们已经检查过 a 不是None之前的。这是非常奇怪的,因为如果我们直接调用foo(a)(没有包装器),它确实可以工作。我正在使用 python 3.6.10 和 mypy 0.740。这是有意的行为吗?如果是这样,您将如何正确输入此内容?
1 回答
蛊毒传说
TA贡献1895条经验 获得超3个赞
这不是由于lambda,而是由于a关闭。简而言之,即使特定代码无法触发错误路径,该函数在技术上也是错误的。
与修复函数中的闭包的类似问题一样,强制在定义时评估名称可以提供有效的类型:
wrapper(lambda a=a: foo(a))
请注意,mypy 无法正确推断lambda类型,因此lambda这样使用仍然会导致错误Cannot infer type of lambda。
考虑完全等效的命名函数:
def l() -> None:
# reveal_type(a) -> Union[builtins.int, None]
return foo(a)
注意这里是如何可见的,而不是守卫之后的a: Optional[int]减少。所以问题不是来自而是来自。a: inta is Nonelambdadef
问题的根源在于 和l的所有值都lambda接近。即使在定义/之前已被拒绝,稍后重置也是有效的。aa: Nonellambdaa
a: Optional[int]
if a is None: exit()
def l() -> None:
# reveal_type(a) -> Union[builtins.int, None]
return foo(a)
a = None
添加回答
举报
0/150
提交
取消