classification
Title: Logical Negation of NotImplemented
Type: enhancement Stage: resolved
Components: Versions: Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Brian.Mearns, r.david.murray
Priority: normal Keywords:

Created on 2014-12-02 14:12 by Brian.Mearns, last changed 2014-12-02 16:02 by r.david.murray. This issue is now closed.

Messages (2)
msg231996 - (view) Author: Maytag Metalark (Brian.Mearns) Date: 2014-12-02 14:12
Performing a logical negation (`not`) on `NotImplemented` should return `NotImplemented`. Currently, it returns `False`.

A common pattern for implementing __eq__ and __ne__ is to implement the comparison in __eq__, and simply delegate to it in __ne__ with a negation. However, if two values are incomparable, then __eq__ and __ne__ should both return NotImplemented. If you try to negate NotImplemented in __ne__, you will end up with a value of False, instead of NotImplemented, so you have to specifically test for this case.

For instance, here is how one would write the code now:

    def __ne__(self, other):
        eq = self.__eq__(other)
        if eq is NotImplemented:
            return NotImplemented
        return not eq

Where as the following would be simpler, and could be used if this change was made:

    def __ne__(self, other):
        return not self.__eq__(other)

This is not simply sugar to reduce typing, it is safer because some coders may forget about NotImplemented and implement __ne__ as shown in the second example anyway, which is not actually correct with the current behavior.
msg232009 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-12-02 16:02
This would break Python's consistency.  'not' of a value returns its boolean inverse, and the boolean value of NotImplemented is True, just like the boolean value of any object that does not have methods that set its boolean value is True.  Having anything that is True return True when not is applied would be even more perverse than NANs are :)

The correct implementation of your __ne__ method is to not define it.  Python will then do the 'not __eq__(other)' call itself.
History
Date User Action Args
2014-12-02 16:02:46r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg232009

resolution: not a bug
stage: resolved
2014-12-02 14:12:04Brian.Mearnscreate