Why does defining the argument types for __eq__ throw a MyPy type error?
Your reading of the docs is right -- you need to give the method (__eq__
) the same signature as it has already in the base class (object
), or else a more permissive one.
The reason for that is that because your MyObject
is a subtype of object
, a MyObject
could be passed anywhere that expects an object
... which means that that code could compare it with any other object
, and there's no legitimate way for the type checker to complain. So, to reflect that, your __eq__
has to be written to expect any object
.
What you can do is right up front in the method's body, check the type and return (or raise an exception):
if not isinstance(other, MyObject):
return False
Then as those docs say, Mypy is smart enough that after that check, it will know that other
is a MyObject
and treat it accordingly.
==
is supposed to take arbitrary other objects, not just objects of your type. If it doesn't recognize the other object, it should return NotImplemented
:
class MyObject(object):
def __init__(self, value: int=5) -> None:
self.value = value
def __eq__(self, other: object) -> bool:
if not isinstance(other, MyObject):
return NotImplemented
return self.value == other.value
NotImplemented
isn't an instance of bool
, but mypy seems to have a weird special case for that. It wants the return annotation to be bool
, and it doesn't complain about the return NotImplemented
line.
Also, if you need to refer to MyObject
for type hints inside its own body, you need to use a string, 'MyObject'
instead of MyObject
. MyObject
doesn't exist yet.