TypeError: 'numpy._DTypeMeta' object is not subscriptable

I'm trying to type hint a numpy ndarray like this:

RGB = numpy.dtype[numpy.uint8] ThreeD = tuple[int, int, int] def load_images(paths: list[str]) -> tuple[list[numpy.ndarray[ThreeD, RGB]], list[str]]: ... 

but at the first line when I run this, I got the following error:

RGB = numpy.dtype[numpy.uint8] TypeError: 'numpy._DTypeMeta' object is not subscriptable 

How do I type hint a ndarray correctly?

2

4 Answers

I had a similar issue with my opencv2 library, which I by upgrading numpy pip install numpy --upgrade

pip install numpy==1.20.0 

will work

It turns out that strongly type a numpy array is not straightforward at all. I spent a couple of hours to figure out how to do it properly.

A simple method that do not add yet another dependency to your project is to use a trick described here. Just wrap numpy types with with ':

import numpy import numpy.typing as npt from typing import cast, Type, Sequence import typing RGB: typing.TypeAlias = 'numpy.dtype[numpy.uint8]' ThreeD: typing.TypeAlias = tuple[int, int, int] NDArrayRGB: typing.TypeAlias = 'numpy.ndarray[ThreeD, RGB]' def load_images(paths: list[str]) -> tuple[list[NDArrayRGB], list[str]]: ... 

The trick is to use single-quotes to avoid the infamous TypeError: 'numpy._DTypeMeta' object is not subscriptable when Python tries to interpret the [] in the expression. This trick is well handled for instance by VSCode Pylance type-checker:

enter image description here

Notice that the colors for types are respected and that the execution gives no error.

Note about nptyping

As suggested by @ddejohn, one can use nptyping. Just install the package: pip install nptyping. However, as of now (16 June 2022), there is no Tuple type defined in nptyping so you won't be able to prefectly type you code that way. I have open a new issue so maybe in the future it will work.

edits

Turns out there is a different way to express a tuple as a nptyping.Shape as answered by ramonhagenaars, which is also elegant:

from nptyping import NDArray, Shape, UInt8 # A 1-dimensional array (i.e. 1 RGB color). RGBArray1D = NDArray[Shape["[r, g, b]"], UInt8] # A 2-dimensional array (i.e. an array of RGB colors). RGBArrayND = NDArray[Shape["*, [r, g, b]"], UInt8] def load_images_trick(paths: list[str]) -> tuple[list[RGBArrayND], list[str]]: ... 

However, this solution is not well supported by VSCode Pylance, an I get an error suggestion for Shape:

Expected class type but received "Literal" "Literal" is not a class "Literal" is not a classPylancereportGeneralTypeIssues Pylance(reportGeneralTypeIssues) 

enter image description here

2

The command np.ndarray[...] raises an exception for certain versions of numpy. The command, typing.TypeAlias used in the accepted answer also raises an exception for certain versions of python, e.g. [1]. I had this issue while collaborating with colleagues with different OS and different python versions. They updated numpy but the error persisted, so I came up with this solution that worked for all of us and still checks for type errors in my machine:

from typing import TYPE_CHECKING if TYPE_CHECKING: from typing import TypeAlias else: TypeAlias = "TypeAlias" NDArrayInt: "TypeAlias" = "np.ndarray[int, np.dtype[np.number]]" NDArrayFloat: "TypeAlias" = "np.ndarray[float, np.dtype[np.number]]" DiscreteMechanism: "TypeAlias" = "Callable[[NDArrayInt], NDArrayInt]" 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like