Typing (numpy.typing
)#
1.20 版本新增。
NumPy API 的大部分具有 PEP 484 風格的類型註解。此外,使用者可以使用許多類型別名,其中最重要的是以下兩個
Mypy 外掛程式#
1.21 版本新增。
一個 mypy 外掛程式,用於管理許多平台特定的註解。其功能可以分為三個不同的部分
指派某些
number
子類別的(平台相關)精度,包括int_
、intp
和longlong
等。請參閱關於 純量類型 的文件,以獲得受影響類別的全面概述。若沒有此外掛程式,所有相關類別的精度將被推斷為Any
。移除所有目標平台上不可用的擴展精度
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#
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#
可以在執行階段變更陣列的 dtype。例如,以下程式碼是有效的
>>> x = np.array([1, 2])
>>> x.dtype = np.bool
類型不允許這種變更。想要編寫靜態類型化程式碼的使用者應改用 numpy.ndarray.view
方法來建立具有不同 dtype 的陣列視圖。
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
的子類型,但是,與執行階段相反,它們不一定被視為子類別。
Timedelta64#
timedelta64
類別在靜態類型檢查時不被視為 signedinteger
的子類別,前者僅繼承自 generic
。
0D 陣列#
在執行階段,numpy 會積極地將任何傳遞的 0D 陣列轉換為其對應的 generic
實例。在引入形狀類型(請參閱 PEP 646)之前,遺憾的是無法在 0D 和 >0D 陣列之間做出必要的區分。雖然這樣做並不完全正確,但目前所有可能執行 0D 陣列 -> 純量轉換的操作都被註解為僅傳回 ndarray
。
如果事先知道某個操作將執行 0D 陣列 -> 純量轉換,則可以考慮使用 typing.cast
或 # type: ignore
註解手動補救這種情況。
Record array dtypes#
numpy.recarray
的 dtype,以及一般的 建立記錄陣列 函式,可以用兩種方式之一指定
直接透過
dtype
引數。最多使用五個輔助引數,這些引數透過
numpy.rec.format_parser
運作:formats
、names
、titles
、aligned
和byteorder
。
這兩種方法目前被類型化為互斥,即如果指定了 dtype
,則不得指定 formats
。雖然在執行階段並未(嚴格)強制執行這種互斥性,但組合使用這兩種 dtype 指定符可能會導致意外甚至完全錯誤的行為。
API#
- numpy.typing.ArrayLike = typing.Union[...]#
一個
Union
,表示可以強制轉換為ndarray
的物件。除其他外,這包括:
純量。
(巢狀)序列。
實作 __array__ 協定的物件。
1.20 版本新增。
另請參閱
- array_like:
任何可以解釋為 ndarray 的純量或序列。
範例
>>> import numpy as np >>> import numpy.typing as npt >>> def as_array(a: npt.ArrayLike) -> np.ndarray: ... return np.array(a)
- numpy.typing.DTypeLike = typing.Union[...]#
-
除其他外,這包括:
1.20 版本新增。
另請參閱
- 指定和建構資料類型
所有可以強制轉換為資料類型的物件的完整概述。
範例
>>> import numpy as np >>> import numpy.typing as npt >>> def as_dtype(d: npt.DTypeLike) -> np.dtype: ... return np.dtype(d)
- numpy.typing.NDArray = numpy.ndarray[tuple[int, ...], numpy.dtype[+_ScalarType_co]][source]#
關於其
dtype.type
的np.ndarray[tuple[int, ...], np.dtype[+ScalarType]]
類型別名 generic。可以在執行階段用於類型化具有給定 dtype 和未指定形狀的陣列。
1.21 版本新增。
範例
>>> import numpy as np >>> import numpy.typing as npt >>> print(npt.NDArray) numpy.ndarray[tuple[int, ...], numpy.dtype[+_ScalarType_co]] >>> print(npt.NDArray[np.float64]) numpy.ndarray[tuple[int, ...], 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)
- class numpy.typing.NBitBase[source]#
一種表示靜態類型檢查期間
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 >>> S = TypeVar("S", bound=npt.NBitBase) >>> T = TypeVar("T", bound=npt.NBitBase) >>> def add(a: np.floating[S], b: np.integer[T]) -> np.floating[S | T]: ... 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*]