Yul*_*ian 5 python type-hinting python-3.x mypy
给出以下代码:
from typing import Optional, Dict
def foo(b: bool) -> Optional[Dict]:
return {} if b else None
def bar() -> None:
d = foo(False)
if not d:
return
filter(lambda x: d['k'], [])
Run Code Online (Sandbox Code Playgroud)
mypy 0.770 失败,最后一行出现以下错误bar
:Value of type "Optional[Dict[Any, Any]]" is not indexable
。同样适用于map
. 将行更改为使用列表理解或pydash 中的filter_
或map_
可以解决该错误。
filter
即使有类型保护,为什么 mypy 在使用标准时也会抛出错误?
mypy
不模拟代码:它不知道是否d
实际到达了None
对的调用filter
。它只知道尝试对静态标记为可能具有None
值的内容进行索引。(换句话说,d
除非您实际分配具有不同静态类型的值,否则 的静态类型不会更改。)
您可以mypy
通过使用该cast
功能来提供帮助。
from typing import Optional, Dict, cast
def foo(b: bool) -> Optional[Dict]:
return {} if b else None
def bar() -> None:
d = foo(False)
if not d:
return
d: dict = cast(dict, d) # "Trust me, mypy: d is a dict"
filter(lambda x: d['k'], [])
Run Code Online (Sandbox Code Playgroud)
if
在or之后发生的类型缩小assert
不会传播到您绑定该变量的内部作用域。简单的解决方法是定义一个与较窄类型绑定的新变量,例如:
def bar() -> None:
d = foo(False)
if not d:
return
d_exists = d
filter(lambda x: d_exists['k'], [])
Run Code Online (Sandbox Code Playgroud)
未绑定到内部作用域中较窄类型的原因d
可能是因为无法保证不会在外部作用域中d
更改回较窄类型,例如:None
def bar() -> None:
d = foo(False)
if not d:
return
def f(x: str) -> str:
assert d is not None # this is totally safe, right?
return d['k'] # mypy passes because of the assert
d = None # oh no!
filter(f, [])
Run Code Online (Sandbox Code Playgroud)
而如果您绑定一个新变量,则无法进行该分配:
def bar() -> None:
d = foo(False)
if not d:
return
d_exists = d
def f(x: str) -> str:
# no assert needed because d_exists is not Optional
return d_exists['k']
d_exists = None # error: Incompatible types in assignment
filter(f, [])
Run Code Online (Sandbox Code Playgroud)
在您的特定示例中,不存在运行时危险,因为lambda
会立即进行评估,同时filter
您没有机会进行更改d
,但 mypy 不一定有一种简单的方法来确定您调用的函数不会挂起该 lambda 并稍后对其进行评估。
归档时间: |
|
查看次数: |
10342 次 |
最近记录: |