Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matrix as dictionary key

I've just started using numpy and its matrix module (very very useful!), and I wanted to use a matrix object as the key of a dictionary, so I checked if matrix had the __hash__ method implemented:

>>> from numpy import matrix
>>> hasattr(matrix, '__hash__')
True

And it does! Nice, so it means that it can be the key of a dictionary:

>>> m1 = matrix('1 2 3; 4 5 6; 7 8 9')
>>> m1
matrix([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])
>>> m2 = matrix('1 0 0; 0 1 0; 0 0 1')
>>> m2
matrix([[1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]])
>>> matrix_dict = {m1: 'first', m2: 'second'}

Worked! Now, let's keep testing:

>>> matrix_dict[m1]
'first'
>>> matrix_dict[matrix('1 2 3; 4 5 6; 7 8 9')]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: matrix([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]])

What? So, it works for the same matrix, but it doesn't work for another matrix with the exact same content? Let's see what __hash__ returns:

>>> hash(m1)
2777620
>>> same_as_m = matrix('1 2 3; 4 5 6; 7 8 9')
>>> hash(same_as_m)
-9223372036851998151
>>> hash(matrix('1 2 3; 4 5 6; 7 8 9')) # same as m too
2777665

So, the __hash__ method of the matrix from numpy returns different values for the same matrix.

Is this right? So, does it means that it cannot be used as a dictionary key? And if it can't be used, why does it have __hash__ implemented?

like image 482
juliomalegria Avatar asked Jan 11 '12 01:01

juliomalegria


People also ask

Can a dictionary have an object as a key?

00:19 A key must be immutable—that is, unable to be changed. These are things like integers, floats, strings, Booleans, functions. Even tuples can be a key. A dictionary or a list cannot be a key.

Can I use a tuple as a dictionary key?

A tuple containing a list cannot be used as a key in a dictionary. Answer: True. A list is mutable. Therefore, a tuple containing a list cannot be used as a key in a dictionary.

How do you access a matrix in Python?

Accessing Values The data elements in a matrix can be accessed by using the indexes. The access method is same as the way data is accessed in Two dimensional array.


1 Answers

It would be wrong to use a mutable object as a key of a dictionary because its hash should change as soon as you change the data, but the value used on insertion will be kept.

On my tests, numpy at Python 3.2.2 raise a TypeError:

TypeError: unhashable type: 'matrix'

But on Python 2.7 it still allows hashing but the hash value never changes when you change data, so it is pretty useless as dictionary key because many matrix objects being added to the dictionary having the same hash will degrade the hash table so insertion will be O(n^2) instead of O(1).

Maybe they didn't remove the hash value to avoid breaking some API on Python 2.x, but do not rely on it!

like image 159
JBernardo Avatar answered Sep 23 '22 03:09

JBernardo