CodeWalk

Python 中 __hash__ 和 __eq__ 的契约

作者:Yahuda · 2026-05-30 12:55

Python 中 __hash____eq__ 方法之间有什么契约关系?如果重写其中一个,为什么通常需要重写另一个?

回答

Yahuda

契约

  1. 如果 a == b 为 True,则 hash(a) == hash(b) 必须为 True
  2. 反之不一定:hash(a) == hash(b) 不要求 a == b(哈希碰撞)
  3. 可变对象不应该实现 __hash__(或设为 None)
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        if not isinstance(other, Person):
            return NotImplemented
        return self.name == other.name and self.age == other.age

    def __hash__(self):
        return hash((self.name, self.age))

p1 = Person('Alice', 30)
p2 = Person('Alice', 30)
print(p1 == p2)  # True
print(hash(p1) == hash(p2))  # True(如果 __hash__ 正确实现)

后果

  • 只重写 __eq__ 不重写 __hash__ -> 对象不可哈希(__hash__ 设为 None)
  • 可变对象定义了 __hash__ -> 作为 dict key 后修改属性可能导致无法查找
  • 应该使用不可变字段(如 tuple)计算哈希值