いくつかの組み合わせをテストすることで簡単に把握できます。これらの2つのタイプを考えてみましょう:
class AlwaysEqualConstantHash:
def __eq__(self, other):
print('AlwaysEqualConstantHash eq')
return True
def __hash__(self):
print('AlwaysEqualConstantHash hash')
return 4
class NeverEqualConstantHash:
def __eq__(self, other):
print('NeverEqualConstantHash eq')
return False
def __hash__(self):
print('NeverEqualConstantHash hash')
return 4
を今度は、辞書内にこれを入れて、何が起こるか見てみましょう:あなたが見ることができるように、ハッシュが辞書に要素に対処するために、すべての時間を使用している
>>> d = {}
>>> d[AlwaysEqualConstantHash()] = 'a'
AlwaysEqualConstantHash hash
>>> d[AlwaysEqualConstantHash()]
AlwaysEqualConstantHash hash
AlwaysEqualConstantHash eq
'a'
>>> d[AlwaysEqualConstantHash()] = 'b'
AlwaysEqualConstantHash hash
AlwaysEqualConstantHash eq
>>> d
{<__main__.AlwaysEqualConstantHash object at 0x00000083E8174A90>: 'b'}
。また、辞書内に同じハッシュを持つ要素があるとすぐに、既存の要素が新しい要素と等しいかどうかを比較するために等価比較も行われます。したがって、新しいすべてのAlwaysEqualConstantHash
オブジェクトは別のものと等しいので、それらはすべて同じキーの辞書として使用できます。
>>> d = {}
>>> d[NeverEqualConstantHash()] = 'a'
NeverEqualConstantHash hash
>>> d[NeverEqualConstantHash()]
NeverEqualConstantHash hash
NeverEqualConstantHash eq
Traceback (most recent call last):
File "<pyshell#56>", line 1, in <module>
d[NeverEqualConstantHash()]
KeyError: <__main__.NeverEqualConstantHash object at 0x00000083E8186BA8>
>>> d[NeverEqualConstantHash()] = 'b'
NeverEqualConstantHash hash
NeverEqualConstantHash eq
>>> d
{<__main__.NeverEqualConstantHash object at 0x00000083E8186F60>: 'a', <__main__.NeverEqualConstantHash object at 0x00000083E8186FD0>: 'b'}
NeverEqualConstantHash
の場合、これは非常に異なります。ハッシュも常に使用されますが、新しいオブジェクトが他のオブジェクトと決して等しくないので、そのように既存のオブジェクトを取得することはできません。我々はいえまったく同じキーを使用している場合は、それ自体が__eq__
を使用して比較する必要がないので
>>> x = NeverEqualConstantHash()
>>> d[x] = 'foo'
NeverEqualConstantHash hash
NeverEqualConstantHash eq
NeverEqualConstantHash eq
>>> d[x]
NeverEqualConstantHash hash
NeverEqualConstantHash eq
NeverEqualConstantHash eq
'foo'
は、我々はまだ要素を取得することができます。この新しいオブジェクトが別のものと等しいかどうかを確認するために、同じハッシュを持つ既存の要素ごとに__eq__
がどのように呼び出されているかもわかります。
だから、ハッシュは要素を辞書に素早くソートするために使われています。また、ハッシュは、等しいと見なされる要素で等しいとする必要があります。既存の要素とのハッシュ衝突の場合のみ、両方のオブジェクトが同じ要素を参照するように__eq__
が使用されています。
あなたの答えをありがとう、非常に有用です – xNJL