如何使包含 numpy 数组的元组可哈希?
How to make a tuple including a numpy array hashable?
使 numpy 数组可哈希的一种方法是将其设置为只读。这在过去对我有用。但是当我在一个元组中使用这样一个 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 首先显示此行为?
到达 hash a numpy array is likely tostring 的最快方法。
In [11]: %timeit hash(y.tostring())
你可以做的不是使用元组定义 class:
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())))
现在您可以在字典中使用它了:
In [21]: ks = KeySet(0, npArray)
In [22]: myDict = {ks: 1}
In [23]: myDict[ks]
Out[23]: 1
您声称
One way to make a numpy array hashable is setting it to read-only
但事实并非如此。将数组设置为只读只会使其成为只读。由于多种原因,它不会使数组可哈希。
第一个原因是 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])
其次,要使可散列性有意义,对象首先必须是 可等化的 - ==
必须是 return 布尔值,并且必须是等价关系。 NumPy 数组不会那样做。散列值的目的是快速定位相等的对象,但是当你的对象甚至没有内置的相等概念时,提供散列值就没有多大意义了。
您不会获得内部包含数组的可散列元组。您甚至不会获得可散列的数组。您可以获得的最接近的方法是将数组数据的一些其他表示形式放入元组中。
使 numpy 数组可哈希的一种方法是将其设置为只读。这在过去对我有用。但是当我在一个元组中使用这样一个 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 首先显示此行为?
到达 hash a numpy array is likely tostring 的最快方法。
In [11]: %timeit hash(y.tostring())
你可以做的不是使用元组定义 class:
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())))
现在您可以在字典中使用它了:
In [21]: ks = KeySet(0, npArray)
In [22]: myDict = {ks: 1}
In [23]: myDict[ks]
Out[23]: 1
您声称
One way to make a numpy array hashable is setting it to read-only
但事实并非如此。将数组设置为只读只会使其成为只读。由于多种原因,它不会使数组可哈希。
第一个原因是 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])
其次,要使可散列性有意义,对象首先必须是 可等化的 - ==
必须是 return 布尔值,并且必须是等价关系。 NumPy 数组不会那样做。散列值的目的是快速定位相等的对象,但是当你的对象甚至没有内置的相等概念时,提供散列值就没有多大意义了。
您不会获得内部包含数组的可散列元组。您甚至不会获得可散列的数组。您可以获得的最接近的方法是将数组数据的一些其他表示形式放入元组中。