-
-
Notifications
You must be signed in to change notification settings - Fork 32k
Clarify the behavior of __eq__() returning NotImplemented #72971
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
Currently, there's no clear statement as to what exactly the fallback is in case |
The documentation of this that comes to mind is spread over <https://docs.python.org/3.6/reference/datamodel.html#object.\_\_eq__\> and <https://docs.python.org/3.6/reference/expressions.html#value-comparisons\>. My understanding of how it works in general is that NotImplemented is just a simple object like None. It doesn’t have any special behaviour on its own. Similarly, if you call a special method like __eq__() manually, there is no fallback, you just get the NotImplemented object. The interpreter calls special methods like __eq__() when evaluating expressions, but the specific behaviour and how NotImplemented is interpreted varies subtly. To evaluate a == b, if b’s class is a strict subclass of a’s class, b.__eq__(a) is tried first, otherwise a.__eq__(b) is tried first. If that call returns NotImplemented, the first fallback is to try the call. Failing that, the final fallback is the default behaviour for object() instances. To evaluate a != b, there is another set of fallbacks in the chain, which is to try “not a.__eq__(b)”. So for __eq__(), the fallback depends on the class hierarchy, on whether a reversed call has already been made, and on whether you are evaluating == or !=. The documentation for comparison operations was cleaned up a while ago (bpo-12067). But there is probably more room for improvement. I think the best thing would be to document the above sort of behaviour as being directly associated with operations like as == and !=, and only indirectly associated with the NotImplemented object and the __eq__() method. |
Martin - what you suggest is precisely what I had in mind (but didn't phrase it as well):
Also a minor typo: you meant "If that call returns NotImplemented, the first fallback is to try the *reverse* call." |
Correct, I meant to say the first fallback is the other call. BTW your suggested text might hold for __eq__(), but for __ne__(), returning NotImplemented seems to bypass the “not a.__eq__(b)” fallback. |
pythonGH-110729) (cherry picked from commit 67f742e) Co-authored-by: Gouvernathor <[email protected]>
pythonGH-110729) (cherry picked from commit 67f742e) Co-authored-by: Gouvernathor <[email protected]>
…ty (GH-110729) (#116254) (cherry picked from commit 67f742e) Co-authored-by: Gouvernathor <[email protected]>
…ty (GH-110729) (#116255) (cherry picked from commit 67f742e) Co-authored-by: Gouvernathor <[email protected]>
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs
The text was updated successfully, but these errors were encountered: