Python 对“元组化”numpy数组的哈希处理
我有一个类叫做 MyClass
,这个类的每个实例都存储了像素的 x 和 y 坐标,这些坐标用两个一维的 numpy 数组表示,而且这两个数组的长度是一样的。如果两个实例的坐标数组完全相同(包括 nan
),那么我们就认为这两个实例是相等的。
我尝试了两种生成哈希值的方法:一种是把两个数组转换成元组,然后对这些元组进行哈希;另一种是对每个数组调用 tobytes()
方法。
class MyClass:
# ... init, doA(), doB(), etc. ...
def __eq__(self, other):
if not type(self) == type(other):
return False
if not np.array_equal(self._x, other._x, equal_nan=True):
return False
if not np.array_equal(self._y, other._y, equal_nan=True):
return False
return True
def hash1(self):
return hash((tuple(self._x), tuple(self._y)))
def hash2(self):
return hash((self._x.tobytes(), self._y.tobytes()))
当我对同一个实例调用 hash1
时,得到的哈希值却不一样,而调用 hash2
每次都输出相同的结果。这两者为什么会有这么大的不同呢?
1 个回答
1
NumPy数组并不是把元素当作Python对象来存储(除非你使用dtype=object)。它存储的是原始的硬件数值。这意味着当你调用tuple
的时候,数组需要为所有的元素创建Python对象。例如,如果你的数组是dtype为float64,数组就得生成numpy.float64
的实例。
数组并不会保存这些包装对象。每次你调用tuple
的时候,数组都会生成新的包装对象。两个值为NaN的numpy.float64
实例并不一定会有相同的哈希值,所以如果你的数组里有NaN,哈希这些元组的结果就不一定是稳定的。