When is __eq__ called with hash ()?

As I mentioned here ,

Below code

class Person(object):
     def __init__(self, name, ssn, address):
         self.name = name
         self.ssn = ssn
         self.address = address
     def __hash__(self):
         print('in hash')
         return hash(self.ssn)
     def __eq__(self, other):
         print('in eq')
         return self.ssn == other.ssn

bob = Person('bob', '1111-222-333', None)

jim = Person('jim bo', '1111-222-333', 'sf bay area')


dmv_appointments = {}
print('calling hash')
dmv_appointments[bob] = 'tomorrow'
print('calling hash')
print(dmv_appointments[jim])
print('calling hash again')
print(dmv_appointments[bob])

Output:

calling hash
in hash
calling hash
in hash
in eq
tomorrow
calling hash again
in hash
tomorrow

Question:

Why __eq__is called when accessing jim, but not on bob?

+6
source share
2 answers

Short answer : Dictionary search first performs (cheap) equality of links ( x is y) when searching in a bucket, and only if this fails, a (more expensive) equality ( x == y) is checked .

Scenario

The function __hash__does not call __eq__ internally. If you create boband jim, such methods are not called.

bob 'tomorrow'. , , bob, . , , bob ( ).

jim. , jim, . . bob. (jim is bob), , . , , bob: 'tomorrow'.

, bob: we , . bob is bob, . (, ). 'tomorrow'.

, , () :

class Person(object):
     def __init__(self, name, ssn, address):
         self.name = name
         self.ssn = ssn
         self.address = address
     def __hash__(self):
         print('in hash')
         return hash(self.ssn)
     def __eq__(self, other):
         print('in eq')
         return False

False . :

>>> bob == bob
in eq
False
>>> bob is bob
True

bob ( , , : , ). , bob 'tomorrow', , bob:

>>> dmv_appointments = {}
>>> dmv_appointments[bob] = 'tomorrow'
in hash
>>> dmv_appointments[bob]
in hash
'tomorrow'
+8

:

__eq__ hash()?

.


:

__eq__ jim, bob?

. , , . , CPython , hash, key value:

hash     | key       | value
-----------------------------------------
    -    |      -    |        -
-----------------------------------------
    -    |      -    |        -

, , hash, hash. , bob, ( - CPython, ) a hash 7475314405837642385. , 2 ( , ), , 7475314405837642385 % 2 == 1:

hash     | key       | value
-----------------------------------------
    -    |      -    |        -
-----------------------------------------
747...385|    bob    |    'tomorrow'

,

, bob:

  • hash: 7475314405837642385
  • : 7475314405837642385 % 21
  • , hash es: 7475314405837642385 == 7475314405837642385
  • , : bob is bobTrue

, 'tomorrow' . jim:

  • hash: 7475314405837642385
  • : 7475314405837642385 % 21
  • , hash es: 7475314405837642385 == 7475314405837642385
  • , : jim is bobFalse
  • jim == bobTrue

, 'tomorrow'.


( ). , hash es lookup is not key and lookup != key, , .

: , , , . :

dmv_appointments = {bob: 1}
bob.ssn = '1'     # changing ssn changes the hash!
dmv_appointments[bob]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-35-3920ada7bab1> in <module>()
     15 dmv_appointments = {bob: 1}
     16 bob.ssn = '1'
---> 17 dmv_appointments[bob]

KeyError: <__main__.Person object at 0x000001BD5DDCC470>

( , hash "" , ).

, , hash , hash, , ! , , , () , , .

+2

All Articles