如何制作包含numpy数组的元组可以使用?

时间:2017-10-26 19:04:03

标签: python-3.x numpy tuples hashable

使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首先会显示这种行为?

2 个答案:

答案 0 :(得分:5)

你声称

  

将numpy数组设为hashable的一种方法是将其设置为只读

但事实并非如此。将数组设置为只读只会使其成为只读。由于多种原因,它不能使阵列可以清洗。

第一个原因是writeable标志设置为False的数组仍然是可变的。首先,您可以随时重新设置writeable=True并继续写入,或者做更多奇特的事情,例如即使shapewriteable,也要重新分配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