2011-02-14 79 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

相关问题