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)(没有包装器),它确实可以工作。我正在使用 python 3.6.10 和 mypy 0.740。


这是有意的行为吗?如果是这样,您将如何正确输入此内容?


叮当猫咪
浏览 83回答 1
1回答

蛊毒传说

这不是由于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: Nonellambdaaa: Optional[int]if a is None: exit()def l() -> None:    # reveal_type(a) -> Union[builtins.int, None]    return foo(a)a = None
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python