Python类实例作字典键:相同哈希却不被识别为重复的原因
自定义类作为字典键时哈希值相同但实例不被识别的原因
你实现了自定义类的__hash__方法,让属性相同的实例哈希值一致,但字典仍无法识别哈希相同的不同实例,核心原因是Python字典判断键是否存在时,不仅依赖哈希值,还会通过__eq__方法验证对象是否相等。
你的示例代码:
class foo: def __init__(self, name, i, j): self.name = name self.i = i self.j = j def __hash__(self): return hash((self.name, self.i, self.j)) bar1 = foo('test', 1, 2) bar2 = foo('test', 1, 2) my_dict = {bar1: 'bar'} print(bar1 in my_dict) # True print(bar2 in my_dict) # False print(hash(bar1) == hash(bar2)) # True
具体原因
Python字典的查找逻辑分为两步:
- 计算目标对象的哈希值,定位到对应的哈希桶;
- 遍历桶内的对象,用
__eq__方法逐一比较,只有当__eq__返回True时,才判定为同一个键。
你的foo类没有重写__eq__方法,Python会使用默认实现——比较对象的内存地址(身份标识)。bar1和bar2是两个独立实例,内存地址不同,所以默认__eq__返回False,即使哈希值相同,字典也不会认为bar2是已存在的键。
解决方法
重写__eq__方法,让属性相同的实例被判定为相等:
class foo: def __init__(self, name, i, j): self.name = name self.i = i self.j = j def __hash__(self): return hash((self.name, self.i, self.j)) def __eq__(self, other): # 先判断类型是否匹配 if not isinstance(other, foo): return False # 比较所有关键属性 return self.name == other.name and self.i == other.i and self.j == other.j
修改后再运行代码,print(bar2 in my_dict)会返回True,符合预期。
内容的提问来源于stack exchange,提问作者iain
相关产品推荐
相关产品推荐

