微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

mypy lambda可选检查

如何解决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

问题的根源是llambda都封闭了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 举报,一经查实,本站将立刻删除。