2013-03-10 25 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

相關問題