Python 对“元组化”numpy数组的哈希处理

0 投票
1 回答
58 浏览
提问于 2025-04-14 16:06

我有一个类叫做 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,哈希这些元组的结果就不一定是稳定的。

撰写回答