使numpy数组hashable的一种方法是将其设置为只读。这在过去对我有用。但是当我在一个元组中使用这样一个numpy数组时,整个元组不再是可以清除的,我不明白。以下是我用来说明问题的示例代码:
import numpy as np
npArray = np.ones((1,1))
npArray.flags.writeable = False
print(npArray.flags.writeable)
keySet = (0, npArray)
print(keySet[1].flags.writeable)
myDict = {keySet : 1}
首先,我创建一个简单的numpy数组并将其设置为只读。然后我将它添加到一个元组并检查它是否仍然是只读的(它是)。
当我想将元组用作字典中的键时,我收到错误TypeError: unhashable type: 'numpy.ndarray'
。
以下是我的示例代码的输出:
False
False
Traceback (most recent call last):
File "test.py", line 10, in <module>
myDict = {keySet : 1}
TypeError: unhashable type: 'numpy.ndarray'
我可以做些什么来使我的元组可以播放?为什么Python首先会显示这种行为?
答案 0 :(得分:5)
你声称
将numpy数组设为hashable的一种方法是将其设置为只读
但事实并非如此。将数组设置为只读只会使其成为只读。由于多种原因,它不能使阵列可以清洗。
第一个原因是writeable
标志设置为False
的数组仍然是可变的。首先,您可以随时重新设置writeable=True
并继续写入,或者做更多奇特的事情,例如即使shape
为writeable
,也要重新分配False
。其次,即使没有触及数组本身,也可以通过另一个writeable=True
的视图来改变其数据。
>>> x = numpy.arange(5)
>>> y = x[:]
>>> x.flags.writeable = False
>>> x
array([0, 1, 2, 3, 4])
>>> y[0] = 5
>>> x
array([5, 1, 2, 3, 4])
其次,为了使hashability有意义,对象必须首先 equatable - ==
必须返回一个布尔值,并且必须是等价关系。 NumPy阵列不会这样做。哈希值的目的是快速定位相同的对象,但是当你的对象甚至没有内置的平等概念时,提供哈希值并不重要。
你不会在里面找到带有数组的可混合元组。你甚至不会得到可清洗的数组。你可以得到的最接近的是将元数据的其他表示形式放在元组中。
答案 1 :(得分:1)
hash a numpy array is likely tostring的最快方式。
In [11]: %timeit hash(y.tostring())
你可以做的不是使用元组定义一个类:
class KeySet(object):
def __init__(self, i, arr):
self.i = i
self.arr = arr
def __hash__(self):
return hash((self.i, hash(self.arr.tostring())))
现在你可以在dict中使用它了:
In [21]: ks = KeySet(0, npArray)
In [22]: myDict = {ks: 1}
In [23]: myDict[ks]
Out[23]: 1