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.
