2011-02-14 74 views
2

我遇到了一個問題,可以正確地散列我的對象。請看下面的代碼:重寫後相同的散列值但不相同的對象__hash__

class Foo: 
    def __init__(self, bar): 
     self.keys = list(bar.keys()) 
     self.values = list(bar.values())  
    def __str__(self): 
     return ', '.join('%s: %s' % z for z in zip(self.keys, self.values))  
    def __hash__(self): 
     return hash(str(self)) 

if __name__ == '__main__': 
    result = set() 
    d = { 1: 2, 3: 4, 5: 6, 7: 8 } 
    for i in range(10): 
     result.add(Foo(d)) 
    for r in result: 
     print r, hash(r) 

我希望得到的結果設置爲包含一個單一的元素,因爲所有增加Foo對象具有相同的內容,因此,相同的哈希。

然而,這是結果:

[email protected]:~/Desktop/stackoverflow$ python hashproblem.py 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 
1: 2, 3: 4, 5: 6, 7: 8 2131119371379196338 

有什麼問題嗎?散列做的看起來一樣,所以不應該被內置的set對象視爲重複對象嗎?爲什麼該集合包含重複項?

我注意到,如果在向該集合添加元素時使用str(Foo(d))而不是Foo(d),那麼事情就會按預期工作。爲什麼這有關係?

Python版本是:

[email protected]:~/Desktop/stackoverflow$ python --version 
Python 2.6.6 

回答

4

由於__hash__方法僅用於內部哈希表,你需要重新定義__eq__爲好。

僅覆蓋__eq__也不正確。如果兩個對象相等,即a.__eq__(b) == True,那麼hash(a)hash(b)也必須相等。

默認__hash__方法是:

def __hash__(self): 
    return id(self) 
+0

謝謝!這似乎工作。我是否需要重寫`__hash__`,或者`__eq__`是否足夠? – misha 2011-02-14 02:42:05

相關問題