考虑这个测试:
class A:
def __init__(self, h):
self.h = h
def __hash__(self):
return self.h
x = A(1)
y = A(2)
a = {x, y}
print x in a, y in a
print a
print "----"
x.h = 2
print x in a, y in a
print a
结果:
True True
set([<__main__.A instance at 0x10d94fd40>, <__main__.A instance at 0x10d94fd88>])
----
False True
set([<__main__.A instance at 0x10d94fd40>, <__main__.A instance at 0x10d94fd88>])
如您所见,第一个对象x
仍然存在,但in
操作员报告它不存在。为什么会这样?
据我了解,Set 对象是使用哈希表实现的,而哈希表通常具有如下结构:
hash_value => list of objects with this hash value
another_hash_value => list of objects with this hash value
当一个 Setin
响应请求时,它首先计算参数的哈希值,然后尝试在相应的列表中找到它。我们的集合a
最初是这样的:
1 => [x]
2 => [y]
现在,我们更改x
的哈希并询问集合是否存在对象。该集合计算哈希值(现在是2
)尝试x
在第二个列表中定位并失败 - 因此False
。
为了让事情更有趣,让我们做
a.add(x)
print x in a, y in a
print a
结果:
True True
set([<__main__.A instance at 0x107cbfd40>,
<__main__.A instance at 0x107cbfd88>,
<__main__.A instance at 0x107cbfd40>])
现在我们在集合中有两次相同的对象!如您所见,没有自动调整,也没有错误。Python 是一种成年人的语言,它总是假设你知道自己在做什么。