Here is a minimal reproducible example:
class Attribut:
def __init__(
self,
name: str,
other_name: str,
):
self.name: str = name
self.other_name: str = other_name
def __eq__(self, other):
if isinstance(other, Attribut):
return self.name == other.name and self.other_name == other.other_name
else:
return NotImplemented
def __hash__(self):
return 0
If I try to do:
a = Attribut("lol", "a")
print(a==4)
I thought I would get NotImplemented
, but instead I get False
.
Also, what is the point of overriding __hash__
, I cannot find a situation where this is useful?
CodePudding user response:
You have to raise an exception, not return it
def __eq__(self, other):
if isinstance(other, Attribut):
return self.name == other.name and self.other_name == other.other_name
else:
raise NotImplemented
Overriding hash method allows you to use other methods that would involve sorting a list of your Attribut objects.
To test it create a script in which you would create such a list
a = [Attribut("lol", "a"), Attribut("lol", "a"), Attribut("lol", "a")]
and then try to make a set out of it
set(a)
If the method hash is implemented in Attribut class then there would be no problem. If not then the program will return an error TypeError: unhashable type: 'Attribut'
CodePudding user response:
When a.__eq__(4)
returns NotImplemented
, you don't get the value back immediately. Instead, Python attempts to call the reflected version of __eq__
(__eq__
itself) with the other argument, namely (4).__eq__(a)
. It's this call that returns False
.
By returning NotImplemented
, you are not saying that self
and other
cannot be compared for equality (for that, raise a ValueError
), but rather that Attribut.__eq__
does not know how to do so, but perhaps the other argument's __eq__
method does.