Search code examples
python-3.xnumpytupleshashable

How to make a tuple including a numpy array hashable?


One way to make a numpy array hashable is setting it to read-only. This has worked for me in the past. But when I use such a numpy array in a tuple, the whole tuple is no longer hashable, which I do not understand. Here is the sample code I put together to illustrate the problem:

import numpy as np

npArray = np.ones((1,1))
npArray.flags.writeable = False
print(npArray.flags.writeable)

keySet = (0, npArray)
print(keySet[1].flags.writeable)

myDict = {keySet : 1}

First I create a simple numpy array and set it to read-only. Then I add it to a tuple and check if it is still read-only (which it is).

When I want to use the tuple as key in a dictionary, I get the error TypeError: unhashable type: 'numpy.ndarray'.

Here is the output of my sample code:

False
False
Traceback (most recent call last):
  File "test.py", line 10, in <module>
    myDict = {keySet : 1}
TypeError: unhashable type: 'numpy.ndarray'

What can I do to make my tuple hashable and why does Python show this behavior in the first place?


Solution

  • The fastest way to hash a numpy array is likely tostring.

    In [11]: %timeit hash(y.tostring())
    

    What you could do is rather than use a tuple define a class:

    class KeySet(object):
        def __init__(self, i, arr):
            self.i = i
            self.arr = arr
        def __hash__(self):
            return hash((self.i, hash(self.arr.tostring())))
    

    Now you can use it in a dict:

    In [21]: ks = KeySet(0, npArray)
    
    In [22]: myDict = {ks: 1}
    
    In [23]: myDict[ks]
    Out[23]: 1