重写__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
对象内容都是一样的,因此它们的哈希值也应该是一样的。
但是,结果却是这样的:
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 个回答
4
查看这个链接:http://docs.python.org/glossary.html#term-hashable - 你还需要实现 __eq__
这个方法。
4
因为 __hash__
方法只是用来处理内部的哈希表,所以你需要同时重新定义 __eq__
方法。
仅仅重写 __eq__
方法也是不够的。如果两个对象是相等的,比如说 a.__eq__(b) == True
,那么 hash(a)
和 hash(b)
的结果也必须相等。
默认的 __hash__
方法是:
def __hash__(self):
return id(self)