为何Python自定义对象集合无法去除text相同的重复项?
问题:自定义对象无法按text属性去重的原因及解决方法
示例代码
class MyObject(object): def __init__(self, no, text): self.no = no self.text = text def __eq__(self, other): if isinstance(other, self.__class__): return self.text == other.text return False def __hash__(self): return hash(str(self)) my_list = {MyObject(1, 'a'), MyObject(2, 'a'), MyObject(0, 'b')} print(my_list)
问题描述
我定义了上述MyObject类,并重写了__eq__和__hash__方法,意图移除text属性相同的重复对象。但运行代码后,打印结果仍显示3个对象,无法去除text为'a'的重复项,请问这是为什么?
原因分析
核心问题出在__hash__方法的实现不符合Python集合去重的规则:
- 当前
__hash__返回hash(str(self)),而Python默认的str(self)会包含对象的内存地址(例如<__main__.MyObject object at 0x10xxxxxx>)。即使两个对象的text属性相同,它们的内存地址唯一,导致str(self)结果不同,哈希值也就不一样。 - Python集合的去重逻辑是:先通过哈希值对元素分组,只有哈希值相同的对象才会触发
__eq__方法比较是否相等。现在两个text为'a'的对象哈希值不同,集合不会进行后续的相等判断,因此会被当作不同元素保留。
解决方法
按照Python的规则,相等的对象必须拥有相同的哈希值,所以__hash__的计算逻辑必须和__eq__的判断依据保持一致——也就是只依赖text属性:
def __hash__(self): return hash(self.text)
修改后,两个text为'a'的对象哈希值相同,集合会调用__eq__方法判断,发现它们相等,最终只会保留其中一个,实现按text属性去重的目的。
内容的提问来源于stack exchange,提问作者marlon
相关产品推荐
相关产品推荐

