如何解决mypy lambda可选检查
我注意到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抱怨此代码段,错误为:Argument 1 to "foo" has incompatible type "None"; expected "int"
。
但是,我们已经检查过a是否不是None
。这是令人惊讶的奇怪,因为如果我们直接调用foo(a)
(没有包装器),它将起作用。
我使用的是mypy 0.740和python 3.6.10。
这是预期的行为吗?如果是这样,您将如何正确输入?
谢谢!
解决方法
这不是由于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: int
后的缩小的a is None
。因此,问题不是出自lambda
,而不是def
。
问题的根源是l
和lambda
都封闭了a
的所有值。即使在定义a: None
/ l
之前拒绝了lambda
,以后重设a
也是有效的。
a: Optional[int]
if a is None: exit()
def l() -> None:
# reveal_type(a) -> Union[builtins.int,None]
return foo(a)
a = None
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。