2017-10-09 48 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>