重写__hash__后,相同的哈希值但不是同一个对象

时间:2011-02-14 02:37:59

标签: python hash override

我遇到问题正确地散列我的对象。请考虑以下代码:

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对象都具有相同的内容,因此具有相同的哈希值。

然而,这是结果:

misha@misha-K42Jr:~/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版本是:

misha@misha-K42Jr:~/Desktop/stackoverflow$ python --version
Python 2.6.6

2 个答案:

答案 0 :(得分:4)

由于__hash__方法仅用于内部哈希表,因此您还需要重新定义__eq__

仅覆盖__eq__也不正确。如果两个对象相等,即a.__eq__(b) == True,那么hash(a)hash(b)也必须相等。

默认的__hash__方法是:

def __hash__(self):
    return id(self)

答案 1 :(得分:4)

请参阅:http://docs.python.org/glossary.html#term-hashable - 您也希望实施__eq__