键入 ( numpy.typing) #

1.20 版本中的新增功能。

NumPy API 的大部分都有PEP 484样式类型注释。此外,用户还可以使用许多类型别名,最重要的是以下两个:

  • ArrayLike:可以转换为数组的对象

  • DTypeLike:可以转换为数据类型的对象

Mypy 插件#

1.21 版本中的新增功能。

一个mypy插件,用于管理许多特定于平台的注释。其功能可以分为三个不同的部分:

  • 分配某些子类的(与平台相关的)精度,包括、和 number 等。有关受影响的类的全面概述,请参阅有关标量类型的文档 。如果没有该插件,所有相关类的精度将被推断为。int_intplonglongAny

  • number删除所有对相关平台不可用的扩展精度子类。最值得注意的是,这包括float128和等complex256。如果没有该插件 ,就 mypy 而言,所有扩展精度类型都将可用于所有平台。

  • 分配 的(依赖于平台的)精度c_intp。如果没有插件,类型将默认为ctypes.c_int64.

    1.22 版本中的新增功能。

例子

要启用该插件,必须将其添加到 mypy配置文件中:

[mypy]
plugins = numpy.typing.mypy_plugin

与运行时 NumPy API 的差异#

NumPy 非常灵活。尝试静态地描述全部可能性会导致类型没有多大帮助。因此,类型化 NumPy API 通常比运行时 NumPy API 更严格。本节介绍一些显着的差异。

类似数组#

ArrayLike类型尝试避免创建对象数组。例如,

>>> np.array(x**2 for x in range(10))
array(<generator object <genexpr> at ...>, dtype=object)

是有效的 NumPy 代码,它将创建一个 0 维对象数组。然而,在使用 NumPy 类型时,类型检查器会抱怨上面的示例。如果您确实打算执行上述操作,那么您可以使用评论:# type: ignore

>>> np.array(x**2 for x in range(10))  # type: ignore

或者显式键入类似数组的对象Any

>>> from typing import Any
>>> array_like: Any = (x**2 for x in range(10))
>>> np.array(array_like)
array(<generator object <genexpr> at ...>, dtype=object)

ndarray #

可以在运行时改变数组的数据类型。例如,以下代码是有效的:

>>> x = np.array([1, 2])
>>> x.dtype = np.bool_

这种类型的突变是不允许的。想要编写静态类型代码的用户应该使用该numpy.ndarray.view 方法来创建具有不同数据类型的数组视图。

DTypeLike #

DTypeLike类型尝试避免使用字段字典创建 dtype 对象,如下所示:

>>> x = np.dtype({"field1": (float, 1), "field2": (int, 3)})

尽管这是有效的 NumPy 代码,但类型检查器会抱怨它,因为不鼓励使用它。请参阅:数据类型对象

数字精度#

子类的精度numpy.number被视为协变通用参数(请参阅 参考资料NBitBase),从而简化了涉及基于精度的铸造的过程的注释。

>>> from typing import TypeVar
>>> import numpy as np
>>> import numpy.typing as npt

>>> T = TypeVar("T", bound=npt.NBitBase)
>>> def func(a: "np.floating[T]", b: "np.floating[T]") -> "np.floating[T]":
...     ...

float16因此, 、float32和 等float64仍然是 的子类型floating,但与运行时相反,它们不一定被视为子类。

时间增量64 #

该类timedelta64不被视为 的子类 signedinteger,前者仅继承于generic while 静态类型检查。

0D 数组#

在运行时,numpy 会积极地将任何传递的 0D 数组转换为相应的generic实例。直到引入形状打字(参见PEP 646)不幸的是不可能对 0D 和 >0D 数组进行必要的区分。虽然这并不严格正确,但所有可能执行 0D 数组的操作 -> 标量转换当前都被注释为专门返回ndarray

如果事先知道某个操作将执行 0D 数组 -> 标量转换,那么可以考虑使用typing.cast或注释手动纠正这种情况。# type: ignore

记录数组数据类型#

的 dtypenumpy.recarray以及numpy.rec一般函数可以通过以下两种方式之一指定:

  • 直接通过dtype论证。

  • 最多有五个通过numpy.format_parser: formatsnamestitles和进行操作的辅助参数alignedbyteorder

这两种方法目前被认为是互斥的, 如果dtype指定了,则可以不指定formats。虽然这种相互排他性在运行时并未(严格)强制执行,但组合两个数据类型说明符可能会导致意外甚至彻头彻尾的错误行为。

API #

numpy.打字。ArrayLike =打字.Union[...] #

AUnion表示可以强制转换为 的对象ndarray

其中包括:

  • 标量。

  • (嵌套)序列。

  • 实现__array__协议的对象。

1.20 版本中的新增功能。

也可以看看

类似数组

任何可以解释为 ndarray 的标量或序列。

例子

>>> import numpy as np
>>> import numpy.typing as npt

>>> def as_array(a: npt.ArrayLike) -> np.ndarray:
...     return np.array(a)
numpy.打字。DTypeLike =打字.Union[...] #

AUnion表示可以强制转换为 的对象dtype

其中包括:

  • type对象。

  • 字符代码或对象名称type

  • 具有.dtype属性的对象。

1.20 版本中的新增功能。

也可以看看

指定和构造数据类型

可以强制转换为数据类型的所有对象的全面概述。

例子

>>> import numpy as np
>>> import numpy.typing as npt

>>> def as_dtype(d: npt.DTypeLike) -> np.dtype:
...     return np.dtype(d)
numpy.打字。NDArray = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]] #

通用版本。np.ndarray[Any, np.dtype[+ScalarType]]

可在运行时用于输入具有给定数据类型和未指定形状的数组。

1.21 版本中的新增功能。

例子

>>> import numpy as np
>>> import numpy.typing as npt

>>> print(npt.NDArray)
numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]]

>>> print(npt.NDArray[np.float64])
numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

>>> NDArrayInt = npt.NDArray[np.int_]
>>> a: NDArrayInt = np.arange(10)

>>> def func(a: npt.ArrayLike) -> npt.NDArray[Any]:
...     return np.array(a)
numpy.typing。NBitBase[来源]#

numpy.number表示静态类型检查期间精度的类型。

专门用于静态类型检查,NBitBase 代表子类分层集的基础。每个后续子类在此用于表示较低的精度水平,例如64Bit > 32Bit > 16Bit

1.20 版本中的新增功能。

例子

下面是一个典型的使用示例:NBitBase此处用于注释一个函数,该函数以任意精度的浮点数和整数作为参数,并返回一个精度最大的新浮点数(例如 )。np.float16 + np.int64 -> np.float64

>>> from __future__ import annotations
>>> from typing import TypeVar, TYPE_CHECKING
>>> import numpy as np
>>> import numpy.typing as npt

>>> T1 = TypeVar("T1", bound=npt.NBitBase)
>>> T2 = TypeVar("T2", bound=npt.NBitBase)

>>> def add(a: np.floating[T1], b: np.integer[T2]) -> np.floating[T1 | T2]:
...     return a + b

>>> a = np.float16()
>>> b = np.int64()
>>> out = add(a, b)

>>> if TYPE_CHECKING:
...     reveal_locals()
...     # note: Revealed local types are:
...     # note:     a: numpy.floating[numpy.typing._16Bit*]
...     # note:     b: numpy.signedinteger[numpy.typing._64Bit*]
...     # note:     out: numpy.floating[numpy.typing._64Bit*]