我有一个类
MyClass
,其中每个实例存储像素的 x 和 y 坐标,表示为两个 1D 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
每次都会输出相同的结果。为什么它们的行为如此不同?
NumPy 数组不会将其元素存储为 Python 对象(除非您使用 dtype=object)。它存储原始硬件数值。这意味着当您调用
tuple
时,数组必须为所有元素创建 Python 对象。例如,如果您的数组的数据类型为 float64,则该数组必须生成 numpy.float64
的实例。
数组不保存这些包装对象。每次调用
tuple
时,数组都会生成新的包装对象。具有 NaN 值的 numpy.float64
的两个实例不能保证散列相同,因此如果您的数组包含 NaN,则散列元组不能保证产生一致的结果。