如何进行仅类型注释的类型断言?

问题描述 投票:0回答:3

我有两个功能:

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
,但这生成了类似的错误

python python-3.x mypy python-typing
3个回答
14
投票

你不会对此感到高兴的。官方设计的向静态类型检查器断言某个值具有特定类型的方法是

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,这会禁用断言。


2
投票

您可以使用

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)


0
投票

我想你正在寻找的是这个:

def f(params):
    # other stuff up here
    foo = get_foo(params)  # type: str  # pytype: disable=annotation-type-mismatch
    return bar(foo)

同意,这并不漂亮,但我相信这正是您所需要的(公平地说,您想要做的也不漂亮)。

© www.soinside.com 2019 - 2024. All rights reserved.