为了账号安全,请及时绑定邮箱和手机立即绑定

mypy lambda 可选检查

mypy lambda 可选检查

叮当猫咪 2024-01-27 15:24:59
我注意到 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


查看完整回答
反对 回复 2024-01-27
  • 1 回答
  • 0 关注
  • 82 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信