This works
range(50)[np.asarray(10)]
This works
{}.get(50)
This doesn't because of unhashable type: 'numpy.ndarray'
{}.get(np.asarray(50))
Is there a reason why __hash__ isn't implemented for this case?
This works
range(50)[np.asarray(10)]
This works
{}.get(50)
This doesn't because of unhashable type: 'numpy.ndarray'
{}.get(np.asarray(50))
Is there a reason why __hash__ isn't implemented for this case?
 
    
    Python dictionaries require their keys to implement both __eq__ and __hash__ methods, and Python's data model requires that:
x == y then hash(x) == hash(y)Numpy's ndarray class overrides __eq__ to support elementwise comparison and broadcasting. This means that for numpy arrays x and y, x == y is not a boolean but another array. This in itself probably rules out ndarrays functioning correctly as dictionary keys.
Even ignoring this quirk of ndarray.__eq__, it would be tricky to come up with a (useful) implementation of ndarray.__hash__. Since the data in a numpy array is mutable, we could not use that data to calculate __hash__ without violating the requirement that the hash of an object does not change during its lifetime.
There is nothing wrong with defining __hash__ for mutable objects provided that the hash itself does not change during the object's lifetime. Similarly, dictionary keys can be mutable provided they implement __hash__ and the hash is immutable. E.g. simple user-defined classes are mutable but can still be used as dictionary keys.
 
    
    This scalar array is regular array with a 0d shape.  Otherwise there's nothing unique about it.
In [46]: x=np.array(10)
In [47]: x
Out[47]: array(10)
In [48]: x[...]=100
In [49]: x
Out[49]: array(100)
You have to extract the number from the array:
In [53]: {}.get(x)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-53-19202767b220> in <module>()
----> 1 {}.get(x)
TypeError: unhashable type: 'numpy.ndarray'
In [54]: {}.get(x.item())
In [58]: {}.get(x[()])
Looking at the hash methods
In [65]: x.__hash__         # None
In [66]: x.item().__hash__
Out[66]: <method-wrapper '__hash__' of int object at 0x84f2270>
In [67]: x[()].__hash__
Out[67]: <method-wrapper '__hash__' of numpy.int32 object at 0xaaab42b0>
