python - mypy lambda 可选检查

标签 python lambda mypy

我注意到 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 提示此代码片段出现错误:“foo”的参数 1 具有不兼容的类型“None”;预期为“int”。 但是,我们之前已经检查过 a 不是 None。这是令人惊讶的奇怪,因为如果我们直接调用 foo(a) (没有包装器),它确实可以工作。 我正在使用 python 3.6.10 和 mypy 0.740。

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

谢谢!

最佳答案

这不是由于 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 is None 保护之后减少的 a: int。所以问题不是来自 lambda,而是来自 def

问题的根源在于 llambda 都对 a所有值进行封闭。即使在定义 l/lambda 之前 a: None 已被拒绝,稍后重置 a 也是有效的.

a: Optional[int]

if a is None: exit()

def l() -> None:
    # reveal_type(a) -> Union[builtins.int, None]
    return foo(a)

a = None

关于python - mypy lambda 可选检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64610100/

相关文章:

python - 强制 mypy 对第三方包进行类型检查

python - 如何取消选择pydatatable中特定索引处的行?

python - 在 python 3 : "compile failed with error code 1" 上通过 pip 安装 scipy 库时出错

python - Geopandas to_crs 转换后给出错误的坐标

c++ - 如何以 lambda 作为第一个参数覆盖可变参数模板?

python - 我可以只对更改的代码执行静态分析吗?

python - 正确键入可以返回提供的默认值的函数

python - 如果为真 : destruct Class

c# - 在 Lambda/LINQ 中组合列表

generics - 在 kotlin 的 lambda 中使用多种泛型类型