You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python集合中哈希值相同的对象为何没有被去重?

>>> class A():
...     def __init__(self):
...             self.x = "the set should have one element"
...     def __hash__(self):
...             return hash(self.x)
... 
>>> ob1 = A()
>>> ob2 = A()
>>> hash(ob1) == hash(ob2)
True
>>> {ob1, ob2}
{<__main__.A object at 0x7f6e2b39b5e0>, <__main__.A object at 0x7f6e2b3a8fd0>}
问题解释

核心原因

Python 集合判断元素重复的逻辑有两个必须同时满足的条件,缺一个都不会触发去重:

  • 两个元素的哈希值相等,即hash(a) == hash(b)返回True
  • 两个对象判断为相等,即a == b返回True

你只重写了__hash__方法,没有重写__eq__方法。自定义类如果没有手动实现__eq__,默认会比较两个对象的内存地址,ob1和ob2是两个独立的实例,内存地址完全不同,所以ob1 == ob2会返回False,哪怕哈希值一致,集合也会认为它们是两个不同的元素,不会去重。

修复验证

只要给类A补充符合预期的__eq__方法,就能实现你要的去重效果:

>>> class A():
...     def __init__(self):
...             self.x = "the set should have one element"
...     def __hash__(self):
...             return hash(self.x)
...     # 补充__eq__方法,按x属性判断两个实例是否相等
...     def __eq__(self, other):
...         if not isinstance(other, A):
...             return False
...         return self.x == other.x
... 
>>> ob1 = A()
>>> ob2 = A()
>>> hash(ob1) == hash(ob2)
True
>>> {ob1, ob2}
{<__main__.A object at 0x7f6e2b39b5e0>}

注意事项

Python 哈希协议明确要求:如果自定义类重写了__hash__方法,就必须同时重写__eq__方法,否则就会出现这类不符合预期的行为。另外只有不可变的自定义类型才适合实现__hash__,如果类的实例属性可以修改,不要重写__hash__,避免实例存入集合/字典后因为属性变化、哈希值变化,出现无法正常读取、删除元素的问题。

内容的提问来源于stack exchange,提问作者Omar Khalid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 21:54:00