2017-11-28 12 views
0

私はこの単純なコードを書いており、私は正確に何が起こっているのかを理解しようとしていました。私はオブジェクトを等しくし、それらのうちの1つだけを辞書に入れました。Pythonの__hash__と__eq__のやりとり

次に、2番目のオブジェクトをキーとして、その値のname属性を出力しようとします。

私のハッシュ関数のおかげで、辞書は、私が挿入したキーに対応するハッシュの値を返します。これはobj1とobj2で同じです。

ここに私の質問です:私のハッシュ関数は、2つのオブジェクトが本当に等しいかどうか、または衝突の場合はチェックしますか?

私は質問がはっきりしていることを願っています。

class Test: 

    def __init__(self, name): 
     self.name = name 

    def __eq__(self, other): 
     return (isinstance(other, type(self)) and self.name == other.name) 


    def __hash__(self): 
     return hash(self.name) 


obj1 = Test('abc') 
obj2 = Test('abc') 

d = {} 

d[obj1] = obj1 

print(d[obj2].name) 

答えて

0

いくつかの組み合わせをテストすることで簡単に把握できます。これらの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__が使用されています。

+0

あなたの答えをありがとう、非常に有用です – xNJL

関連する問題