<p>约翰·米利金提出了一个类似的解决方案:</p>
<pre><code>class A(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
def __eq__(self, othr):
return (isinstance(othr, type(self))
and (self._a, self._b, self._c) ==
(othr._a, othr._b, othr._c))
def __hash__(self):
return hash((self._a, self._b, self._c))
</code></pre>
<p>这个解决方案的问题是<code>hash(A(a, b, c)) == hash((a, b, c))</code>。换句话说,散列与其关键成员的元组冲突。也许这在实践中并不重要?</p>
<p>更新:Python文档现在建议使用一个元组,如上面的例子所示。请注意,文档说明</p>
<blockquote>
<p>The only required property is that objects which compare equal have the same hash value</p>
</blockquote>
<p>请注意,事实并非如此。不比较等于<em>的对象可能具有相同的哈希值。这种散列冲突在用作dict键或set元素时不会导致一个对象替换另一个对象,只要这些对象不同时比较equal</em>。</p>
<h2>过时/错误的解决方案</h2>
<p><s>该<a href="http://docs.python.org/3/reference/datamodel.html#object.__hash__" rel="nofollow noreferrer">Python documentation on ^{<cd2>}</a>建议使用类似于XOR的东西组合子组件的散列,这给了我们:</p>
<pre><code>class B(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
def __eq__(self, othr):
if isinstance(othr, type(self)):
return ((self._a, self._b, self._c) ==
(othr._a, othr._b, othr._c))
return NotImplemented
def __hash__(self):
return (hash(self._a) ^ hash(self._b) ^ hash(self._c) ^
hash((self._a, self._b, self._c)))
</code></pre>
<p>更新:正如Blckknght指出的,更改a、b和c的顺序可能会导致问题。我添加了一个附加的<code>^ hash((self._a, self._b, self._c))</code>来捕获被散列的值的顺序。如果无法重新排列要组合的值(例如,如果它们具有不同的类型,因此<code>_a</code>的值永远不会分配给<code>_b</code>或<code>_c</code>等),则可以删除最后的<code>^ hash(...)</code>。</p>