如何为np.recarray添加具体的类型注解?
关于numpy.recarray的Mypy类型标注问题
我在scratch.py中有以下代码:
import numpy as np def my_array(arr: np.recarray) -> None: print(arr.x) my_array(np.rec.array([(1.0, 2), (3.0, 4)], dtype=[('x', '<f8'), ('y', '<i8')]))
运行命令mypy scratch.py --disallow-any-generics后,出现如下错误:
scratch.py:3: error: Missing type parameters for generic type "recarray" [type-arg]
用Any临时消除错误
以下代码可以规避上述错误,但类型标注不够精确:
def my_array(arr: np.recarray[Any, Any]) -> None: print(arr.x)
尝试更精确的类型标注(未成功)
我希望使用更具体的类型,比如这样的写法,但无法通过Mypy检查:
def my_array(arr: np.recarray[np.dtype[[('x', float), ('y', int)]]]) -> None: print(arr.x)
可通过检查但原理存疑的代码
下面这段代码能通过Mypy检查,但我不清楚原因:
from typing import Union import numpy as np def my_array(arr: np.recarray[Union[float, int], np.dtype[Union[np.float_, np.int_]]]) -> None: print(arr.x) my_array(np.rec.array([(1.0, 2), (3.0, 4)], dtype=[('x', '<f8'), ('y', '<i8')]))
为什么这段代码能通过检查
np.recarray的泛型签名是recarray[ShapeType, DType]:
- 第一个泛型参数
ShapeType指代数组的形状类型(通常是整数元组,比如Tuple[int, int]表示二维数组),你写的Union[float, int]属于宽松写法,Mypy会将其视为兼容任意形状,不会触发错误 - 第二个参数
DType对应数组的 dtype,np.dtype[Union[np.float_, np.int_]]表示该 dtype 可以是浮点或整型,刚好匹配你定义的复合 dtype(包含float64和int64两种类型),因此Mypy判定类型兼容
更精确的标注方案
如果想要严格匹配你的结构化 dtype,可以用类型别名配合numpy.typing.NDArray(recarray本质上是NDArray的子类):
import numpy as np from numpy.typing import NDArray from typing import TypeAlias # 定义对应结构化dtype的类型别名 MyRecordDtype: TypeAlias = np.dtype[ [('x', np.float64), ('y', np.int64)] ] def my_array(arr: NDArray[MyRecordDtype]) -> None: print(arr.x) my_array(np.rec.array([(1.0, 2), (3.0, 4)], dtype=[('x', '<f8'), ('y', '<i8')]))
这样既符合Mypy的严格校验,又能精准标注输入的类型。
内容的提问来源于stack exchange,提问作者Victory Omole
相关产品推荐
相关产品推荐

