如何为集合包含测试实现__eq__?

15 投票
2 回答
10449 浏览
提问于 2025-04-17 18:36

我遇到了一个问题,我在一个集合里添加了一个对象,然后想检查这个对象是否在集合中。虽然我重写了 __eq__() 方法,但在检查的时候并没有调用这个方法。我是不是需要重写 __hash__() 方法呢?如果是的话,我该怎么实现 __hash__(),因为我需要对元组、列表和字典进行哈希处理?

class DummyObj(object):

    def __init__(self, myTuple, myList, myDictionary=None):
        self.myTuple = myTuple
        self.myList = myList
        self.myDictionary = myDictionary

    def __eq__(self, other):
        return self.myTuple == other.myTuple and \
            self.myList == other.myList and \
            self.myDictionary == other.myDictionary

    def __ne__(self, other):
        return not self.__eq__(other)

if __name__ == '__main__':

    list1 = [1, 2, 3]
    t1    = (4, 5, 6)
    d1    = { 7 : True, 8 : True, 9 : True }
    p1 = DummyObj(t1, list1, d1)

    mySet = set()

    mySet.add(p1)

    if p1 in mySet:
        print "p1 in set"
    else:
        print "p1 not in set"

2 个回答

-3

我猜可能是 __eq____ne__ 这两个方法在用 'in' 操作符比较对象时没有被 Python 调用。我不太确定具体的“丰富比较”操作符是什么,查了文档也没找到,但如果你重写 __cmp__ 方法,应该能解决你的问题,因为如果没有更合适的“丰富比较”操作符,Python 默认会用这个方法来比较对象。

14

来自集合的文档

集合类是通过字典来实现的。因此,集合元素的要求和字典键的要求是一样的;也就是说,元素需要定义两个方法:__eq__() 和 __hash__()。

__hash__ 函数的文档建议将组成部分的哈希值进行异或运算(xor)。正如其他人提到的,通常不建议对可变对象进行哈希,但如果你真的需要这样做,这种方法是可行的:

class DummyObj(object):

    ...

    def __hash__(self):
        return (hash(self.myTuple) ^
                hash(tuple(self.myList)) ^
                hash(tuple(self.myDictionary.items())))

并且检查一下它是否有效:

p1 = DummyObj(t1, list1, d1)
p2 = DummyObj(t1, list1, d1)
mySet = set()
mySet.add(p1)

print "p1 in set", p1 in mySet
print "p2 in set", p2 in mySet

这将打印:

$ python settest.py 
p1 in set True
p2 in set True

撰写回答