2013-03-10 24 views
10

我遇到了一个问题,即将实例添加到集合中,然后再进行测试以查看该集合中是否存在该对象。我已覆盖__eq__(),但在包含测试期间它不会被调用。我必须重写__hash__()吗?如果是这样,我将如何实现__hash__(),因为我需要散列元组,列表和字典?如何实现__eq__集合包含测试?

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" 
+0

也许你可以为我们写单元测试,你希望成功?我用你的代码得到'set'中的p1。我应该得到别的东西吗? – hughdbrown 2013-03-10 20:11:30

+2

散列可变对象通常不是一个好主意... – mgilson 2013-03-10 20:11:53

+0

请参阅http://wiki.python.org/moin/DictionaryKeys,为什么@mgilson是正确的。 – delnan 2013-03-10 20:12:32

回答

10

documentation on sets

集合类是使用字典来实现。因此,设置元素的 要求与字典 键的要求相同;即元素定义了__eq __()和__hash __()。

__hash__ function documentation建议将组件的哈希值映射到一起。正如其他人所说,这是一般不哈希可变对象是个好主意,但如果你真的需要,这个工程:

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 
-3

嗯,我的猜测是比较使用“在”操作对象时__eq____ne__可能不Python调用。我不确定特定的“丰富比较”操作符是什么,查看文档,但是覆盖__cmp__应该解决您的问题,因为如果没有实现更合适的“富比较”操作符,python默认使用它来执行对象比较。

+1

你错了。 '__eq__'和'__ne__'工作得很好,问题是缺少(定制的,正确的)散列函数。 – delnan 2013-03-10 20:25:35

+0

如果你只是猜测,你为什么会回答? – Alan 2015-01-14 02:27:50

相关问题