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