-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
delegation of !=
to the right-hand side argument is not always done
#65607
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
$ ~/Projects/cpython/3.4/python -c '
class Foo(object):
def __ne__(self, other):
return "yup"
def __eq__(self, other):
return "nope" class Bar(object):
pass
print(object() != Foo(), object() == Foo())
print(Bar() != Foo(), Bar() == Foo())
'
yup nope
False nope
$ The output I would expect from this is
That is, even when the type of the left-hand argument is not a base class of the type of the right-hand argument, delegation to the right-hand argument is sensible if the left-hand argument does not implement the comparison. Note that the output also demonstrates that this is already the behavior for |
That's because the implicit default __ne__ on Bar returns the opposite of __eq__. |
Why would an subclass of object that doesn't redefine either __eq__ or __ne__ have a different behavior for inequality than object itself? Bar never defined __eq__, so it shouldn't have an implicit __ne__ any more than object itself does... Saying that Bar has an implicit __ne__ that object doesn't is answering how this happens, but it's not a why; is there a reason why this should be the case, or is this a bug (either in spec or in code) that should be fixed? |
The reason I don't know whether it's a bug. |
I don't think it's a bug. The subclass-goes-first behavior is very intentional. The implicit __ne__ returning the boolean inverse of __eq__ is what fooled me when I looked at it. Or did you mean that following the subclass rule in the case where object is the other class is possibly suspect? |
The subclass behavior is a red herring. I meant maybe object.ne should check if the other object has a ne method before falling back on |
Oh, I see. Yes, that would seem more consistent. |
There is a bit of analysis of the object.__ne__() implementation in bpo-4395. If my understanding is correct, I think it is a bug that object.__ne__(self, other) evaluates “not self == other”. It should evaluate “not self.__eq__(other)” instead, so that NotImplemented can be caught, allowing the reflected other.__ne__(self) method to be tried. |
This patch should fix the problem I think. Before the __ne__() implementation was calling the “==” operator; now it calls the __eq__() method instead. Also includes extra test for bpo-4395 to avoid having conficting patches. |
Particular case of this bug: >>> class A:
... def __eq__(self, other): return NotImplemented
...
>>> A().__eq__(object())
NotImplemented
>>> A().__ne__(object())
True The second result should be NotImplemented. Martin's patch LGTM except few style nitpicks to tests. |
There are few incorrect implementations of __ne__ in the stdlib. Updated patch removes them. May be we should remove all implementations of __ne__ which are redundant now. |
I looked over your __ne__ removals from the library, and they all seem sensible to me. |
New changeset e516badfd3b2 by Serhiy Storchaka in branch '3.4': New changeset 7e9880052401 by Serhiy Storchaka in branch 'default': |
Thank you for your contribution Martin. |
New changeset 3603bae63c13 by Serhiy Storchaka in branch 'default': |
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:
The text was updated successfully, but these errors were encountered: