这有效
range(50)[np.asarray(10)]
这有效
{}.get(50)
这不是因为unhashable type: 'numpy.ndarray'
{}.get(np.asarray(50))
有没有理由为这种情况实施__hash__
?
答案 0 :(得分:2)
Python词典需要其键来实现__eq__
和__hash__
方法,Python的数据模型要求:
x == y
则hash(x) == hash(y)
Numpy的ndarray
课程覆盖__eq__
以支持元素比较和广播。这意味着对于numpy数组x
和y
,x == y
不是布尔值而是另一个数组。这本身可能会排除ndarray
正确运行的字典键。
即使忽略ndarray.__eq__
的这个怪癖,提出ndarray.__hash__
的(有用的)实现也会很棘手。由于numpy数组中的数据是可变的,因此我们无法使用该数据来计算__hash__
,而不会违反对象的哈希值在其生命周期内不会更改的要求。
为可变对象定义__hash__
没有任何问题,前提是散列本身在对象的生命周期内不会发生变化。类似地,字典键可以是可变的,只要它们实现__hash__
并且散列是不可变的。例如。简单的用户定义类是可变的,但仍可用作字典键。
答案 1 :(得分: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>