-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
__i<magic>__ method incompatible with __<magic>__ of superclass #6225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
There are lots of subtle special-casing in how Python calls
Unfortunately, they are not documented, and every time I am asked about this I spend an hour to write an example of unsafe behavior. @Michael0x2a you probably have the most context about this. Will you have time to write some docs about dunder related additional checks/errors? (Probably the docs should be in https://mypy.readthedocs.io/en/latest/common_issues.html) |
I did some poking around and it looks like this error message was intended to handle the following case:
This program is indeed not typesafe: at runtime, the final type of The error message correctly flags that Child's However, this check doesn't seem to take into account to take into account is if Parent also defines an So basically, I think @Levitanus's code snippet ought to type-check, unless I'm missing something. Anyways, I'll submit a PR to enhance this check and also look into improving either our error messages or our docs, as you suggested. |
Hmm, actually, I think @Levitanus's code snippet is actually not typesafe if the child class is allowed to arbitrarily return
In fact, if we assume any operator method can return
So now I'm confused -- what even is our policy regarding |
Sorry, I missed something... Why is runtime type is int? It has to be 'A'. class A:
value: int
def __add__(self, other) -> int:
assert isinstance(other, int)
return self.value + other
def __iadd__(self, other) -> 'A':
if not isinstance(other, int):
# also, I'm not a pro programmer, but it seemed to me that raise TypeError
# is common solution at this case
return NotImplemented
# here we are making assignement operation.
# Can be Your case with "quasi immutable new A()"
return A(self.__add__(other))
# or
self.value = self.__add__(other)
return self So, my point of view that P.S.
And this point I now understand and conclude)) |
@Levitanus -- you should try running the code samples I posted. In short, if some binary operator method returns NotImplemented, it's a signal meaning that it doesn't know what to do with the incoming type. Python will then try using the "next" operator method that can potentially return a reasonable result. For example, if Here, if This is basically why it's important for the behavior of |
@Michael0x2a I think we had a similar discussion in #4985. The conclusion was that:
In this case we should probably try to allow something like this: class B:
def __iadd__(self, other) -> B:
...
class C(B):
def __iadd__(self, other) -> C:
... since it is quite typical pattern. |
(Anyway, documenting all kinds of unsafe operator overlap checks and their limitations is important independently of what we will decide here.) |
Triggered by the requirements for type-checking, these two have the same signature. And it just makes sense! REF: python/mypy#6225 #648
Triggered by the requirements for type-checking, these two have the same signature. And it just makes sense! REF: python/mypy#6225 #648
I'm recieving an a error within folowing code:
I'm not sure that
__add__
and__iadd__
methods have to be compatible.And, if belief to the MyPy in the signature of class A, that not produce the error, MyPy also doesn't think they have to be compatible...
The text was updated successfully, but these errors were encountered: