Added in version 1.20.
Large parts of the NumPy API have
-style type annotations. In addition a number of type aliases are available to users, most prominently the two below:
: objects that can be converted to arrays
: objects that can be converted to dtypes
Differences from the runtime NumPy API
NumPy is very flexible. Trying to describe the full range of possibilities statically would result in types that are not very helpful. For that reason, the typed NumPy API is often stricter than the runtime NumPy API. This section describes some notable differences.
ArrayLike
The
type tries to avoid creating object arrays. For example,
>>> np.array(x**2forxinrange(10))array(<generator object <genexpr> at ...>, dtype=object)is valid NumPy code which will create a 0-dimensional object array. Type checkers will complain about the above example when using the NumPy types however. If you really intended to do the above, then you can either use a #type:ignore comment:
>>> np.array(x**2forxinrange(10))# type: ignoreor explicitly type the array like object as
:
>>> fromtypingimportAny>>> array_like:Any=(x**2forxinrange(10))>>> np.array(array_like)array(<generator object <genexpr> at ...>, dtype=object)DTypeLike
The
type tries to avoid creation of dtype objects using dictionary of fields like below:
>>> x=np.dtype({"field1":(float,1),"field2":(int,3)})Although this is valid NumPy code, the type checker will complain about it, since its usage is discouraged. Please see :
Number precision
The precision of
subclasses is treated as an invariant generic parameter (see
), simplifying the annotating of processes involving precision-based casting.
>>> fromtypingimportTypeVar>>> importnumpyasnp>>> importnumpy.typingasnpt>>> T=TypeVar("T",bound=npt.NBitBase)>>> deffunc(a:np.floating[T],b:np.floating[T])->np.floating[T]:... ...Consequently, the likes of
,
and
are still sub-types of
, but, contrary to runtime, they’re not necessarily considered as sub-classes.
Deprecated since version 2.3: The
helper is deprecated and will be removed in a future release. Prefer expressing precision relationships via typing.overload or TypeVar definitions bounded by concrete scalar classes. For example:
fromtypingimportTypeVarimportnumpyasnpS=TypeVar("S",bound=np.floating)deffunc(a:S,b:S)->S:...or in the case of different input types mapping to different output types:
fromtypingimportoverloadimportnumpyasnp@overloaddefphase(x:np.complex64)->np.float32:...@overloaddefphase(x:np.complex128)->np.float64:...@overloaddefphase(x:np.clongdouble)->np.longdouble:...defphase(x:np.complexfloating)->np.floating:...Timedelta64
The
class is not considered a subclass of
, the former only inheriting from
while static type checking.
Record array dtypes
The dtype of
, and the
functions in general, can be specified in one of two ways:
Directly via the dtype argument.
With up to five helper arguments that operate via
: formats, names, titles, aligned and byteorder.
These two approaches are currently typed as being mutually exclusive, i.e. if dtype is specified than one may not specify formats. While this mutual exclusivity is not (strictly) enforced during runtime, combining both dtype specifiers can lead to unexpected or even downright buggy behavior.
API
ndarray
The
class is a
that accepts two type arguments:
The type of
, which must be a tuple of int, e.g. tuple[int,int] (2-D shape) or tuple[()] (0-D shape). The default shape is tuple[Any,...], which represents an unknown shape with any number of dimensions. Currently, Literal ints or other more specific types are not supported.
The type of
, which must be a subtype of
such as numpy.dtype[numpy.float64]. If omitted, it will default to numpy.dtype[Any].
>>> importnumpyasnp>>> typeImageRGB=np.ndarray[tuple[int,int,int],np.dtype[np.uint8]]>>> typeVector[S:np.generic]=np.ndarray[tuple[int],np.dtype[S]]numpy.typing.ArrayLike=typing.Union[...]
A
representing objects that can be coerced into an
.
Among others this includes the likes of:
Scalars.
(Nested) sequences.
Objects implementing the __array__ protocol.
Added in version 1.20.
See Also
:Any scalar or sequence that can be interpreted as an ndarray.
Examples
>>> importnumpyasnp>>> importnumpy.typingasnpt>>> defas_array(a:npt.ArrayLike)->np.ndarray:... returnnp.array(a)
numpy.typing.DTypeLike=typing.Union[...]
A
representing objects that can be coerced into a
.
Among others this includes the likes of:
objects.
Character codes or the names of
objects.
Objects with the .dtype attribute.
Added in version 1.20.
Examples
>>> importnumpyasnp>>> importnumpy.typingasnpt>>> defas_dtype(d:npt.DTypeLike)->np.dtype:... returnnp.dtype(d)numpy.typing.NDArray=NDArray
A
np.ndarray[tuple[Any, ...], np.dtype[ScalarT]]
type alias
w.r.t. its
.
Can be used during runtime for typing arrays with a given dtype and unspecified shape.
Added in version 1.21.
Examples
>>> importnumpyasnp>>> importnumpy.typingasnpt>>> print(npt.NDArray)NDArray>>> print(npt.NDArray[np.float64])NDArray[numpy.float64]>>> NDArrayInt=npt.NDArray[np.int_]>>> a:NDArrayInt=np.arange(10)>>> deffunc(a:npt.ArrayLike)->npt.NDArray[Any]:... returnnp.array(a)classnumpy.typing.NBitBase
A type representing
precision during static type checking.
Used exclusively for the purpose of static type checking,
represents the base of a hierarchical set of subclasses. Each subsequent subclass is herein used for representing a lower level of precision, e.g.64Bit>32Bit>16Bit.
Added in version 1.20.
Deprecated since version 2.3: Use @typing.overload or a TypeVar with a scalar-type as upper bound, instead.
Examples
Below is a typical usage example:
is herein used for annotating a function that takes a float and integer of arbitrary precision as arguments and returns a new float of whichever precision is largest (e.g.np.float16+np.int64->np.float64).
>>> fromtypingimportTYPE_CHECKING>>> importnumpyasnp>>> importnumpy.typingasnpt>>> defadd[S:npt.NBitBase,T:npt.NBitBase](... a:np.floating[S],b:np.integer[T]... )->np.floating[S|T]:... returna+b>>> a=np.float16()>>> b=np.int64()>>> out=add(a,b)>>> ifTYPE_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*]