这个问题可能已经有了答案,所以如果您知道的话,请指导我找到答案。我自己找不到这个问题,尽管这个问题感觉很常见。
因此,请考虑以下模式:
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])
通过 mypy
和 pyright
的类型检查,并输出
# 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/