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

Dan*_*ats 6 python python-3.x mypy python-typing

我有两个功能:

def get_foo(params) -> Optional[str]
def bar(foo: str)
Run Code Online (Sandbox Code Playgroud)

以及将这些函数链接在一起的函数:

def f(params):
    # other stuff up here
    foo = get_foo(params)
    return bar(foo)
Run Code Online (Sandbox Code Playgroud)

我知道基础上,其他的事情在我的函数的结果发生的事情get_foo永远没有了。

当我运行mypy这个文件时,我当然会得到错误:

error: Argument 1 of "bar" has incompatible type "Optional[str]"; expected "str"
Run Code Online (Sandbox Code Playgroud)

这是有道理的。

我可以添加一个assert foo is not None语句,但这是热路径代码,在我的测试中它具有可衡量的性能影响。我只想为 mypy 做一个类型断言。我怎么做?

编辑:我也尝试#type: str在赋值语句后添加注释,但这产生了类似的错误

use*_*ica 7

你不会对此感到高兴。官方设计的向静态类型检查器断言值具有特定类型的方法是typing.cast,这是一个具有实际运行时成本的实际函数,我相信比您想要替换的昂贵assert。它只是原封不动地返回它的第二个参数,但它仍然有函数调用开销。Python 的类型注释系统不是用零开销类型断言语法设计的。

作为替代方案,您可以将其Any用作“逃生舱口”。如果您foo使用 type 进行注释Any,则 mypy 应该允许bar调用。局部变量注释没有运行时成本,因此唯一的运行时成本是额外的局部变量存储和查找:

from typing import Any

def f(params):
    foo: Any = get_foo(params)
    return bar(foo)
Run Code Online (Sandbox Code Playgroud)

除此之外,您最好的选择可能是使用assert并运行带有-O禁用断言的标志的Python 。

  • 谢谢,非常感谢您的回答,我将其标记为已接受。然而,这确实感觉像是 mypy 中缺少的功能。相比之下,TypeScript 允许[通过类型断言手动缩小类型](https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions)。但是,在上面的示例中,如果将“Any”更改为“str”,则会生成错误。 (5认同)
  • @KFL 虽然 ``cast`` 不执行任何操作,但它仍然是一个需要查找和调用的函数。在 Python 中,函数调用(即使是恒等函数)也不是免费的。 (3认同)