Python 类型提示 - 更好的 cast() 语法?

0x5*_*453 10 python type-hinting mypy

我最近开始在我的代码中使用类型提示,到目前为止发现它们(大部分)非常有用。

但是,我真正不喜欢的一件事是强制类型检查器假定变量属于某种类型的语法。鉴于这个例子:

import itertools
from typing import Iterable, Tuple
x: Iterable[Tuple[str, str]] = itertools.combinations('abc', 2)
# error: Incompatible types in assignment (expression has type "Iterable[Tuple[str, ...]]", variable has type "List[Tuple[str, str]]")
Run Code Online (Sandbox Code Playgroud)

据我所知,解决此问题的推荐方法是明确cast对象以强制类型检查器使用指定的类型,例如:

import itertools
from typing import Iterable, Tuple, cast
x = cast(Iterable[Tuple[str, str]], itertools.combinations('abc', 2))
Run Code Online (Sandbox Code Playgroud)

我个人觉得这个解决方案有点恶心。我主要担心的是,对于没有经验的读者来说,不清楚cast是否纯粹是为了帮助静态分析器。(如果我还不知道,我会根据名称和上下文假设它正在转换并复制到指定类型的对象,而实际上没有运行时成本。)

cast看起来像任何旧的函数调用。当我看到对某个值调用了一个函数时,我希望该值发生变异和/或发生其他一些副作用,但在这种情况下,唯一的副作用是mypy停止抱怨。类型提示本身具有独特的语法,但我觉得这使新类型语法和传统 Python 语法的混合使线条变得模糊。(它已经有点模糊,因为您必须import使用类型并可以组合它们,但这是另一个讨论。)

是否有cast类似行为的替代语法?我还没有找到任何东西,但我希望有类似的东西:

x1 = itertools.combinations('abc', 2)) # cast: Iterable[Tuple[str, str]] 

x2: Iterable[Tuple[str, str]] = itertools.combinations('abc', 2)) # type: cast

x3: Cast[Iterable[Tuple[str, str]]] = itertools.combinations('abc', 2))
Run Code Online (Sandbox Code Playgroud)

Seb*_*eft 2

实际上,最新版本的 Mypy 确实返回了正确的类型Iterator[Tuple[str, str]]

此更改是在 PR https://github.com/python/typeshed/pull/4309中引入到 Typeshed 中的。

如果您无法将 mypy 更新到最新版本,您可以从 中签出最新版本typeshed并使用 config 选项custom_typeshed_dir

有关更多详细信息,请参阅https://mypy.readthedocs.io/en/stable/config_file.html#confval-custom_typeshed_dir 。