Reputation: 2356
Has anyone implemented type hinting for the specific numpy.ndarray
class?
Right now, I'm using typing.Any
, but it would be nice to have something more specific.
For instance if the NumPy people added a type alias for their array_like object class. Better yet, implement support at the dtype level, so that other objects would be supported, as well as ufunc.
Upvotes: 217
Views: 198919
Reputation: 7639
Numpy 1.21 includes a numpy.typing
module with an NDArray
generic type.
numpy.typing.NDArray = numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]]
A generic version of
np.ndarray[Any, np.dtype[+ScalarType]]
.Can be used during runtime for typing arrays with a given dtype and unspecified shape.
Examples:
>>> 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)
As of 2024-10-04, support for shapes is still a work in progress per numpy/numpy#16544.
Upvotes: 111
Reputation: 21
numpy-typing makes type hinting way more useful and compact :
array3D:np.float32_3d[ax.x, ax.y, ax.z] = np.zeros((3, 3, 3))
It means that "array3D" is a 3d array of float32 where the first axis corresponds to the x coordinate, the second y coordinate, and the last z coordinate. The lib is very flexible and supports large typing annotations.
Upvotes: 2
Reputation: 13485
At my company we've been using:
from typing import TypeVar, Generic, Tuple, Union, Optional
import numpy as np
Shape = TypeVar("Shape")
DType = TypeVar("DType")
class Array(np.ndarray, Generic[Shape, DType]):
"""
Use this to type-annotate numpy arrays, e.g.
image: Array['H,W,3', np.uint8]
xy_points: Array['N,2', float]
nd_mask: Array['...', bool]
"""
pass
def compute_l2_norm(arr: Array['N,2', float]) -> Array['N', float]:
return (arr**2).sum(axis=1)**.5
print(compute_l2_norm(arr = np.array([(1, 2), (3, 1.5), (0, 5.5)])))
We actually have a MyPy checker around this that checks that the shapes work out (which we should release at some point). Only thing is it doesn't make PyCharm happy (ie you still get the nasty warning lines):
Upvotes: 36
Reputation: 231385
Check recent numpy versions for a new typing
module
https://numpy.org/doc/stable/reference/typing.html#module-numpy.typing
It looks like typing
module was developed at:
https://github.com/python/typing
The main numpy
repository is at
https://github.com/numpy/numpy
Python bugs and commits can be tracked at
The usual way of adding a feature is to fork the main repository, develop the feature till it is bomb proof, and then submit a pull request. Obviously at various points in the process you want feedback from other developers. If you can't do the development yourself, then you have to convince someone else that it is a worthwhile project.
cython
has a form of annotations, which it uses to generate efficient C
code.
You referenced the array-like
paragraph in numpy
documentation. Note its typing
information:
A simple way to find out if the object can be converted to a numpy array using array() is simply to try it interactively and see if it works! (The Python Way).
In other words the numpy
developers refuse to be pinned down. They don't, or can't, describe in words what kinds of objects can or cannot be converted to np.ndarray
.
In [586]: np.array({'test':1}) # a dictionary
Out[586]: array({'test': 1}, dtype=object)
In [587]: np.array(['one','two']) # a list
Out[587]:
array(['one', 'two'],
dtype='<U3')
In [589]: np.array({'one','two'}) # a set
Out[589]: array({'one', 'two'}, dtype=object)
For your own functions, an annotation like
def foo(x: np.ndarray) -> np.ndarray:
works. Of course if your function ends up calling some numpy
function that passes its argument through asanyarray
(as many do), such an annotation would be incomplete, since your input could be a list
, or np.matrix
, etc.
When evaluating this question and answer, pay attention to the date. 484 was a relatively new PEP back then, and code to make use of it for standard Python still in development. But it looks like the links provided are still valid.
Upvotes: 75
Reputation: 1212
nptyping adds lots of flexibility for specifying numpy type hints.
Upvotes: 13
Reputation: 51
What i did was to just define it as
Dict[Tuple[int, int], TYPE]
So for example if you want an array of floats you can do:
a = numpy.empty(shape=[2, 2], dtype=float) # type: Dict[Tuple[int, int], float]
This is of course not exact from a documentation perspective, but for analyzing correct usage and getting proper completion with pyCharm it works great!
Upvotes: -3