Why does defining argument types for __eq__ raise an error like MyPy?

I am using Python 3.5.1 and the recently released MyPy v0.4.1 static type analyzer.

I have more complicated code that I have reduced to this simplest possible python class needed to reproduce the error:

class MyObject(object): def __init__(self, value: int=5) -> None: self.value = value def __eq__(self, other: MyObject) -> bool: return self.value == other.value 

Running a check like mypy test.py causes the following error:

 test.py: note: In class "MyObject": test.py:5: error: Argument 1 of "__eq__" incompatible with supertype "object" 

My theory, based on these documents , is that __eq__ and __neq__ on the object already have types defined that __eq__ with my subclass redefinition of these types. My question is how to define these types to make sure that __eq__ type checked with my selected type.

+5
source share
2 answers

== it is supposed to use arbitrary other objects, and not just objects of your type. If it does not recognize another 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 

Also, if you need to call MyObject for type hints inside your own body, you need to use the string 'MyObject' instead of MyObject . MyObject does not exist yet.

+4
source

Your reading of documents is correct - you need to give the method ( __eq__ ) the same signature as in the base class ( object ), or more permissive.

The reason for this is that since your MyObject is a subtype of object , a MyObject can be passed anywhere where an object is expected ... which means that this code could compare it to any other object , and there is no legal way to check type to complain. So, to reflect this, your __eq__ must be written to wait for any object .

What you can do is right in the body of the method, check the type and return (or throw an exception):

 if not isinstance(other, MyObject): return False 

Then, as these documents say , Mypy is smart enough that after this check, he will know that other is MyObject and treat it accordingly.

+2
source

All Articles