jubueche
jubueche

Reputation: 793

Python: Accessing dict with hashable object fails

I am using a hashable object as a key to a dictionary. The objects are hashable and I can store key-value-pairs in the dict, but when I create a copy of the same object (that gives me the same hash), I get a KeyError.

Here is some small example code:

class Object:
    def __init__(self, x): self.x = x
    def __hash__(self): return hash(self.x)

o1 = Object(1.)
o2 = Object(1.)
hash(o1) == hash(o2) # This is True
data = {}
data[o1] = 2.
data[o2] # Desired: This should output 2.

In my scenario above, how can I achieve that data[o2] also returns 2.?

Upvotes: 2

Views: 136

Answers (3)

RomainL.
RomainL.

Reputation: 1014

So as stated before your object need to implement __ eq__ trait (equality ==), If you want to understand why:

Sometimes hash of different object are the same, this is called collision. Dictionary manages that by testing if the objects are equals. If they are not dictionary has to manage the collision. How they do that Is implementation details and can vary a lot. A dummy implementation would be list of tuple key value.

Under the hood, a dummy implementation may look like that :

dico[key] = [(object1, value), (object2, value)]

Upvotes: 1

Bharel
Bharel

Reputation: 26900

You need to implement both __hash__ and __eq__:

class Object:
    def __init__(self, x): self.x = x
    def __hash__(self): return hash(self.x)
    def __eq__(self, other): return self.x == other.x if isinstance(other, self.__class__) else NotImplemented

Per Python documentation:

if a class does not define an __eq__() method it should not define a __hash__() operation either

After finding the hash, Python's dictionary compares the keys using __eq__ and realize they're different, that's why you're not getting the correct output.

Upvotes: 4

Allan Chua
Allan Chua

Reputation: 10175

You can use the __eq__ magic method to implement a equality check on your object.

    def __eq__(self, other):
        if (isinstance(other, C)):
            return self.x == self.x

You can learn more about magic methods from this link.

Upvotes: 2

Related Questions