预分配列表时的 Python 类型转换

标签 python mypy typing

这个问题可能已经有了答案,所以如果您知道的话,请指导我找到答案。我自己找不到这个问题,尽管这个问题感觉很常见。

因此,请考虑以下模式:

arr = [None] * n
for i in range(n):
    # do some computations
    # ...
    # even more computations
    arr[i] = MyClass(some_computed_value)

到目前为止一切顺利,我倾向于不时使用这种模式。现在,让我们彻底尝试为所有代码提供类型注释。问题是我们用 None 预分配了数组,因此它的类型为 list[None]。但我们希望它是list[MyClass]。我们该如何进行?

最直接的解决方案是使其可选:

arr: list[Optional[MyClass]] = [None] * n

这解决了类型检查器问题,但现在这是我们的问题,因为 Optional 禁止我们对结果执行甚至基本的操作

arr[0].my_method()
# error: NoneType has no attribute "my_method"

长话短说,我最终得到以下模式:

arr_: Any = [None] * n
for i in range(n):
    # ...
    arr_[i] = MyClass(some_computed_value)
arr = typing.cast(list[MyClass], arr_)

这是丑陋的、不方便的、难以阅读的、样板的。你做什么?

最佳答案

当您第一次初始化 arr 时,您可以对类型检查器撒谎,以“欺骗”它 arr 永远不包含 None 条目。出于静态类型检查的目的,arr 将是一个 list[MyClass],即使它在运行时短暂包含 None 条目。当然,您有责任确保这一假设得到实现。

例如,

from typing import cast, reveal_type

n = 1000

arr: list[int] = [cast(int, None)] * n
# or alternatively
arr: list[int] = [None] * n # type: ignore

for i in range(n):
    arr[i] = i

reveal_type(arr)
reveal_type(arr[0])

通过 mypypyright 的类型检查,并输出

# mypy
tmp.py:9: note: Revealed type is "builtins.list[builtins.int]"
tmp.py:10: note: Revealed type is "builtins.int"
Success: no issues found in 1 source file

# pyright
file.py
  file.py:9:13 - information: Type of "arr" is "list[int]"
  file.py:10:13 - information: Type of "arr[0]" is "int"
0 errors, 0 warnings, 2 informations

关于预分配列表时的 Python 类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76694215/

相关文章:

python - 为什么 PIPE 文件的 readline() 如此慢?

python - 使用 matplotlib,使日期刻度不重叠

python-3.x - Mypy 迭代器和生成器有什么区别?

python - 为什么 Sequence 是 mypy 中不支持的 + 操作数类型?

python - 读取同一行中多个项目的项目

python - 在 Panda/Python 中绘制一行

python - 如何确定 python 中任何生成器的产量/发送/返回值

python - *(解包)运算符可以在 Python 中输入吗?或者任何其他可变参数函数使得所有可变类型都在结果类型中?

javascript - 检测用户何时开始/停止在 jquery 中输入

python - 属性错误 : module 'typing' has no attribute 'GenericMeta'