I want to define a hashable class with mutable fields, but if I define the __eq__
method myself (which definitely I want to do), it is no longer hashable by default and I need to define __hash__
method as well.
If I define the __hash__
method such that it just compares the id()
values like it (I think) did by default before I defined __eq__
I get weird results.
According to this question, I have to define __eq__
the same way as __hash__
but I would like to understand why this is the case and, if possible, how to work around that.
To be specific, I want to define objects with two mutable fields containing integers:
class CustomObj:
def __init__(self, a, b):
self.a = a
self.b = b
ObjA = CustomObj(1, 2)
ObjB = CustomObj(1, 2)
I want to be able to compare them to each other ObjA == ObjB
, as well as to simple tuples ObjA == (1, 2)
. I also want to be able to store them in a set myset = set()
, so that I can check both (1, 2) in myset
and ObjA in myset
for the same result. How can I achieve this?
This is my code at the moment, but it's definitely not behaving correctly:
class Agent:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
try:
# Try comparing two agents
return (self.x == other.x and self.y == other.y
and isinstance(other, Agent))
except AttributeError:
# If it fails, compare an agent and a tuple
if isinstance(other, tuple) and len(other) == 2:
return self.x == other[0] and self.y == other[1]
else:
return NotImplemented
def __hash__(self):
return id(self)