mypy lambda 可选检查
mypy lambda optional check
我注意到 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。
这是有意为之的行为吗?如果是这样,您将如何正确输入?
谢谢!
这不是因为 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
.
问题的根源在于 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
我注意到 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。
这是有意为之的行为吗?如果是这样,您将如何正确输入?
谢谢!
这不是因为 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
.
问题的根源在于 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