2012-01-11 102 views
6
如果 matrix__hash__方法来实现

我刚刚使用numpy及其matrix模块(非常非常有用!)开始,我想用一个矩阵对象作为字典的关键,所以我检查:矩阵作为字典键

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

它确实!很好,所以这意味着它可以成为字典的关键:

>>> 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'} 

工作!现在,让我们继续测试:

>>> 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]]) 

什么?所以,它适用于相同的矩阵,但它不适用于具有完全相同内容的另一个矩阵?让我们来看看__hash__回报:

>>> 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 

所以,从matrix回报numpy不同值的相同matrix__hash__方法。

这是正确的吗?那么,这是否意味着它不能用作字典键?如果不能使用,为什么要执行__hash__

+4

默认情况下Python对象是可散列的 - 您必须为不可用的类禁用它。可能仅仅是'numpy'的一部分。 – millimoose 2012-01-11 02:06:51

+0

矩阵是一个ndarray,默认情况下它们也是可散列的 - 我假设你也有同样的问题。 – jozzas 2012-01-11 02:41:41

+0

@jozzas,我很惊讶有可能使用矩阵作为字典键,因为我知道ndarrays不能用作键,矩阵是ndarray的子​​类 – 2012-01-11 02:54:59

回答

9

使用可变对象作为字典的关键字是错误的,因为只要您更改数据,它的哈希值就会改变,但插入时使用的值将会保留。

在我的测试中,在numpy的Python的3.2.2引发TypeError:

TypeError: unhashable type: 'matrix' 

但在Python 2.7版它仍然允许散列但是,当你更改数据的哈希值永远不会改变,所以它是相当无用字典键,因为许多matrix对象被添加到具有相同散列的字典中会降低散列表,因此插入将是O(n^2)而不是O(1)

也许他们没有删除哈希值以避免在Python 2.x上打破某些API,但不要依赖它!