Typing (numpy.typing)#
New in version 1.20.
Large parts of the NumPy API havePEP 484-style type annotations. Inaddition a number of type aliases are available to users, most prominentlythe two below:
ArrayLike: objects that can be converted to arraysDTypeLike: objects that can be converted to dtypes
Mypy plugin#
New in version 1.21.
Amypy plugin for managing a number of platform-specific annotations.Its functionality can be split into three distinct parts:
Assigning the (platform-dependent) precisions of certain
numbersubclasses, including the likes ofint_,intpandlonglong. See the documentation onscalar types for a comprehensive overviewof the affected classes. Without the plugin the precision of all relevantclasses will be inferred asAny.Removing all extended-precision
numbersubclasses that areunavailable for the platform in question. Most notably this includes thelikes offloat128andcomplex256. Without the pluginallextended-precision types will, as far as mypy is concerned, be availableto all platforms.Assigning the (platform-dependent) precision of
c_intp.Without the plugin the type will default toctypes.c_int64.New in version 1.22.
Deprecated since version 2.3:Thenumpy.typing.mypy_plugin entry-point is deprecated in favor ofplatform-agnostic static type inference. Removenumpy.typing.mypy_plugin from theplugins section of your mypyconfiguration; if that surfaces new errors, please open an issue with aminimal reproducer.
Examples#
To enable the plugin, one must add it to their mypyconfiguration file:
[mypy]plugins=numpy.typing.mypy_plugin
Differences from the runtime NumPy API#
NumPy is very flexible. Trying to describe the full range ofpossibilities statically would result in types that are not veryhelpful. For that reason, the typed NumPy API is often stricter thanthe runtime NumPy API. This section describes some notabledifferences.
ArrayLike#
TheArrayLike type tries to avoid creating object arrays. Forexample,
>>>np.array(x**2forxinrange(10))array(<generator object <genexpr> at ...>, dtype=object)
is valid NumPy code which will create a 0-dimensional objectarray. Type checkers will complain about the above example when usingthe NumPy types however. If you really intended to do the above, thenyou can either use a#type:ignore comment:
>>>np.array(x**2forxinrange(10))# type: ignore
or explicitly type the array like object asAny:
>>>fromtypingimportAny>>>array_like:Any=(x**2forxinrange(10))>>>np.array(array_like)array(<generator object <genexpr> at ...>, dtype=object)
ndarray#
It’s possible to mutate the dtype of an array at runtime. For example,the following code is valid:
>>>x=np.array([1,2])>>>x.dtype=np.bool
This sort of mutation is not allowed by the types. Users who want towrite statically typed code should instead use thenumpy.ndarray.viewmethod to create a view of the array with a different dtype.
DTypeLike#
TheDTypeLike type tries to avoid creation of dtype objects usingdictionary 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 :Data type objects
Number precision#
The precision ofnumpy.number subclasses is treated as a invariant genericparameter (seeNBitBase), simplifying the annotating of processesinvolving 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 offloat16,float32 andfloat64 are still sub-types offloating, but, contrary toruntime, they’re not necessarily considered as sub-classes.
Deprecated since version 2.3:TheNBitBase helper is deprecated and will be removed in a future release. Prefer expressing precision relationships viatyping.overload orTypeVar 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#
Thetimedelta64 class is not considered a subclass ofsignedinteger, the former only inheriting fromgenericwhile static type checking.
0D arrays#
During runtime numpy aggressively casts any passed 0D arrays into theircorrespondinggeneric instance. Until the introduction of shapetyping (seePEP 646) it is unfortunately not possible to make thenecessary distinction between 0D and >0D arrays. While thus not strictlycorrect, all operations that can potentially perform a 0D-array -> scalarcast are currently annotated as exclusively returning anndarray.
If it is known in advance that an operationwill perform a0D-array -> scalar cast, then one can consider manually remedying thesituation with eithertyping.cast or a#type:ignore comment.
Record array dtypes#
The dtype ofnumpy.recarray, and theCreating record arraysfunctions in general, can be specified in one of two ways:
Directly via the
dtypeargument.With up to five helper arguments that operate via
numpy.rec.format_parser:formats,names,titles,alignedandbyteorder.
These two approaches are currently typed as being mutually exclusive,i.e. ifdtype is specified than one may not specifyformats.While this mutual exclusivity is not (strictly) enforced during runtime,combining both dtype specifiers can lead to unexpected or even downrightbuggy behavior.
API#
- numpy.typing.ArrayLike=typing.Union[...]#
A
Unionrepresenting objects that can be coercedinto anndarray.Among others this includes the likes of:
Scalars.
(Nested) sequences.
Objects implementing the__array__ protocol.
New in version 1.20.
See Also
- array_like:
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
Unionrepresenting objects that can be coercedinto adtype.Among others this includes the likes of:
New in version 1.20.
See Also
- Specifying and constructing data types
A comprehensive overview of all objects that can be coercedinto data types.
Examples
>>>importnumpyasnp>>>importnumpy.typingasnpt>>>defas_dtype(d:npt.DTypeLike)->np.dtype:...returnnp.dtype(d)
- numpy.typing.NDArray=numpy.ndarray[tuple[typing.Any,...],numpy.dtype[~_ScalarT]]#
A
np.ndarray[tuple[Any,...],np.dtype[ScalarT]]type aliasgeneric w.r.t. itsdtype.type.Can be used during runtime for typing arrays with a given dtypeand unspecified shape.
New in version 1.21.
Examples
>>>importnumpyasnp>>>importnumpy.typingasnpt>>>print(npt.NDArray)numpy.ndarray[tuple[typing.Any, ...], numpy.dtype[~_ScalarT]]>>>print(npt.NDArray[np.float64])numpy.ndarray[tuple[typing.Any, ...], numpy.dtype[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[source]#
A type representing
numpy.numberprecision during static type checking.Used exclusively for the purpose of static type checking,
NBitBaserepresents the base of a hierarchical set of subclasses.Each subsequent subclass is herein used for representing a lower levelof precision,e.g.64Bit>32Bit>16Bit.New in version 1.20.
Deprecated since version 2.3:Use
@typing.overloador aTypeVarwith a scalar-type as upperbound, instead.Examples
Below is a typical usage example:
NBitBaseis herein used for annotatinga function that takes a float and integer of arbitrary precisionas arguments and returns a new float of whichever precision is largest(e.g.np.float16+np.int64->np.float64).>>>fromtypingimportTypeVar,TYPE_CHECKING>>>importnumpyasnp>>>importnumpy.typingasnpt>>>S=TypeVar("S",bound=npt.NBitBase)>>>T=TypeVar("T",bound=npt.NBitBase)>>>defadd(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*]