2017-10-09 21 views
2

这工作使用标ndarrays作为键

range(50)[np.asarray(10)] 

这工作

{}.get(50) 

这并不是因为unhashable type: 'numpy.ndarray'

{}.get(np.asarray(50)) 

是有一个原因__hash__尚未实现对于这种情况?

+0

如果要切实做到这一点,看到了这个问题:HTTPS:/ /stackoverflow.com/questions/16589791/most-efficient-property-to-hash-for-numpy-array但这不是你的问题的答案,为什么? – plan

+0

'hash'没有为'list'实现(也不是'dict')。它是为不可变的'tuple'实现的。即使对于[50]也是如此。字典的“关键字”必须是不可变的。数组或列表的索引可以是一个可变数字。作为一个规则'标量ndarrays'没有什么用处,除了作为一个多维数组的副产品。 – hpaulj

回答

2

Python字典要求其键同时实现__eq____hash__方法,以及Python的数据模型要求:

  1. 对象的哈希值不其生命周期内改变
  2. 如果x == y然后hash(x) == hash(y)

Numpy的ndarray类改写__eq__支持元素比较和广播。这意味着对于numpy数组xy,x == y不是一个布尔值而是另一个数组。这本身可能会排除ndarray作为字典键正常工作。

即使忽略这个ndarray.__eq__的怪癖,想出一个ndarray.__hash__的(有用的)实现会很棘手。由于numpy数组中的数据是可变的,因此我们无法使用该数据来计算__hash__而不违反对象的哈希在其生命周期中不会更改的要求。

定义__hash__可变对象没有问题,前提是散列本身在对象的生命周期中不会更改。类似地,字典键可以是可变的,只要它们实现__hash__并且散列是不可变的。例如。简单的用户定义的类是可变的,但仍可以用作字典键。

2

这个scalar array是一个0d形状的规则数组。否则,没有什么特别的。

In [46]: x=np.array(10) 
In [47]: x 
Out[47]: array(10) 
In [48]: x[...]=100 
In [49]: x 
Out[49]: array(100) 

你必须提取数组数:

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

望着hash方法

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>