我有两个功能:
def get_foo(params) -> Optional[str]
def bar(foo: str)
还有一个将这些函数链接在一起的函数:
def f(params):
# other stuff up here
foo = get_foo(params)
return bar(foo)
根据我的函数中发生的其他事情,我知道
get_foo
的结果将 never 为 None。
当我针对此文件运行
mypy
时,我当然会收到错误:
error: Argument 1 of "bar" has incompatible type "Optional[str]"; expected "str"
这是有道理的。
我可以添加一个
assert foo is not None
语句,但这是热路径代码,在我的测试中它具有可测量的性能影响。 我只想为 mypy 进行类型断言。我该怎么做?
编辑:我还尝试在赋值语句后添加注释
#type: str
,但这生成了类似的错误
你不会对此感到高兴的。官方设计的向静态类型检查器断言某个值具有特定类型的方法是
typing.cast
,这是一个具有实际运行时成本的实际函数,我相信更比你想要替换的assert
贵。它只是返回第二个参数不变,但仍然有函数调用开销。 Python 的类型注释系统并不是采用零开销类型断言语法设计的。
作为替代方案,您可以使用
Any
作为“逃生舱口”。如果您使用 foo
类型注释 Any
,mypy 应允许 bar
调用。局部变量注释没有运行时成本,因此唯一的运行时成本是额外的局部变量存储和查找:
from typing import Any
def f(params):
foo: Any = get_foo(params)
return bar(foo)
除此之外,您最好的选择可能是使用
assert
并使用 -O
标志运行 Python,这会禁用断言。
您可以使用
TYPE_CHECKING
变量,在运行时为 False
,但在类型检查期间为 True
。这将避免 assert
的性能影响:
from typing import TYPE_CHECKING
def f(params):
# other stuff up here
foo = get_foo(params)
if TYPE_CHECKING:
assert foo is not None
return bar(foo)
我想你正在寻找的是这个:
def f(params):
# other stuff up here
foo = get_foo(params) # type: str # pytype: disable=annotation-type-mismatch
return bar(foo)
同意,这并不漂亮,但我相信这正是您所需要的(公平地说,您想要做的也不漂亮)。