13

我遇到了一个问题,我将一个实例添加到集合中,然后进行测试以查看该对象是否存在于该集合中。我已经覆盖__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"
4

2 回答 2

12

关于集合的文档

集合类是使用字典实现的。因此,对集合元素的要求与对字典键的要求相同;也就是说,该元素同时定义了 __eq__() 和 __hash__()。

__hash__ 函数文档建议将组件的哈希值异或在一起。正如其他人所提到的,散列可变对象通常不是一个好主意,但如果你真的需要,这很有效:

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
于 2013-03-10T20:14:40.773 回答
-3

好吧,当使用“in”运算符比较对象时,我的猜测会__eq____ne__不会被 python 调用。我不确定具体的“丰富比较”运算符是什么,查看文档,但是__cmp__如果没有实现更合适的“丰富比较”运算符,则覆盖应该可以解决您的问题,因为 python 默认使用它来执行对象比较。

于 2013-03-10T20:20:44.033 回答