Numpy: ndarray哈希
在本文中,我们将介绍Numpy的ndarray哈希性质。哈希是一种将任意长度的消息压缩到某一固定长度的消息摘要的算法。Numpy数组(ndarray)是一种可变对象,并且不能作为哈希表的键值。这是由于Python哈希表依赖于键的哈希值来确定键的内存位置,不可变对象的哈希值是不变的,因此可以安全地作为键值使用,而可变对象的哈希值可以随着对象的状态而改变,因此不能安全地作为键值使用。
为了解决这个问题,Numpy提供了两种方法来使ndarray成为可哈希对象:通过定义不可变对象来实现哈希,或者使用numpy.ndarray.view
方法。
阅读更多:Numpy 教程
定义不可变对象
如果你只需要对ndarray进行一些简单的操作,如查找、散列等,那么你可以定义一个只读的元组(tuple),其中包含ndarray的元素值。由于元组是不可变对象,因此可以安全地将其作为哈希表的键值使用。例如:
import numpy as np
arr = np.array([1, 2, 3])
t = tuple(arr)
print(hash(t)) # 输出1624454310598751525
使用numpy.ndarray.view方法
如果你需要对ndarray进行修改操作,那么定义不可变对象可能会失去一些灵活性。在这种情况下,你可以使用numpy.ndarray.view
方法来为ndarray创建一个只读视图,相当于只读的快照。该方法返回一个新的ndarray对象,但是它并不拥有原始对象数据的所有权,因此原始对象可以被自由地修改。例如:
import numpy as np
arr = np.array([1, 2, 3])
v = arr.view()
print(hash(v)) # 输出528463297570618168
需要注意的是,由于视图对象只是原始数组的快照,因此它们不应被修改。以下代码说明了这一点:
import numpy as np
arr = np.array([1, 2, 3])
v = arr.view()
# 错误:视图对象不可变
v[0] = 9
视图对象可以用作哈希表的键值,但是如果对原始数组进行修改,则可能会导致视图对象比较时不相等。例如:
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
v1 = arr1.view()
v2 = arr2.view()
d = {v1: 'a', v2: 'b'}
print(d) # 输出{array([1, 2, 3], dtype=int64): 'a', array([4, 5, 6], dtype=int64): 'b'}
arr1[0] = 9 # 对原始数组进行修改
print(d) # 输出{array([9, 2, 3], dtype=int64): 'a', array([4, 5, 6], dtype=int64): 'b'}
即使视图对象指向相同的数据,当原始数组发生更改时,它们也不能相等。原因是,视图内存中存储的是指针而不是数据。
总结
在本文中,我们介绍了Numpy的ndarray哈希性质。由于ndarray是可变对象,不能直接作为哈希表的键值。为了解决这个问题,我们可以定义不可变元组或使用numpy.ndarray.view
方法创建只读视图。但是需要注意的是,视图对象只是原始数组的快照,不能被直接修改。如果对原始数组进行修改,可能会导致视图对象比较时不相等。