d.b
d.b

Reputation: 493

np.uint16 isn't the same as np.uint16

I'm attempting to map numpy dtypes to associated values using a dictionary lookup. I observe the following counterintuitive behavior:

dtype = np.uint16
x = np.array([0, 1, 2], dtype=dtype)
assert x.dtype == dtype
d = {np.uint8: 8, np.uint16: 16, np.uint32: 32, np.float32: 32}
print(dtype in d)  # prints True
print(x.dtype in d)  # prints False

Using other dtypes produces similar results.

So we have that np.uint16 == x.dtype, but the former is found in the dictionary's keys while the latter is not. Any explanation and/or simple workaround would be appreciated.

Upvotes: 7

Views: 12041

Answers (3)

user2357112
user2357112

Reputation: 281843

Dtypes don't work like they look at first glance. np.uint16 isn't a dtype object. It's just convertible to one. np.uint16 is a type object representing the type of array scalars of uint16 dtype.

x.dtype is an actual dtype object, and dtype objects implement == in a weird way that's non-transitive and inconsistent with hash. dtype == other is basically implemented as dtype == np.dtype(other) when other isn't already a dtype. You can see the details in the source.

Particularly, x.dtype compares equal to np.uint16, but it doesn't have the same hash, so the dict lookup doesn't find it.

Upvotes: 10

DaveIdito
DaveIdito

Reputation: 1606

This is the expected behavior:

np.uint16 is non-initialized and therefore dtype is actually a class, whereas x.dtype is actually a data type object (documentation).

Another answer shows a workaround here.

Upvotes: 1

Joffrey Schmitz
Joffrey Schmitz

Reputation: 2438

x.dtype returns a dtype object (see dtype class)

To get the type inside, you need to call x.dtype.type :

print(x.dtype.type in d) # True

Upvotes: 2

Related Questions