Reputation: 793
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
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
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
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