What is the evaluation order of __hash__ and __eq__ for Python dict?

I am trying to figure out what Python dictionaries need to do internally to find the key. It seems to me that the hash will be evaluated first, and if there is a collision, Python will iterate over the keys until it finds one for which eq returns True. This makes me wonder why the following code works (test code only for understanding internal components):

class MyClass(object): def __eq__(self, other): return False def __hash__(self): return 42 if __name__=='__main__': o1 = MyClass() o2 = MyClass() d = {o1: 'o1', o2: 'o2'} assert(o1 in d) # 1 assert(d[o1]=='o1') # 2 assert(o2 in d) # 3 assert(d[o2]=='o2') # 4 

If the dictionary cannot find the correct key (returning either "o1" or "o2" in both cases No. 2 and No. 4 or throwing an error, depending on the internal implementation). How can he land on the correct key in both cases, when he can never correctly "equalize" the keys (since eq returns False).

All the documentation I saw in hashing always mentions hash and eq together, never cmp , ne , etc., which makes me think that these 2 are the only ones that play a role in this scenario.

+5
source share
1 answer

Everything that you use as a dict key should satisfy the invariant that bool(x == x) is True . (I would just say x == x , but there are reasonable objects for which this is not even logical.)

The disk assumes that this will be executed, so the procedure that it uses to verify key equality actually checks the identity of the object before using == . This preliminary check is an implementation detail; you should not rely on this happening or not happening.

Reasonable objects for which (x == x) is not True include float('nan') and numpy.array([1, 2]) .

+5
source

All Articles