Should __ne__ be implemented as the negation of __eq__? Should __ne__ be implemented as the negation of __eq__? python python

Should __ne__ be implemented as the negation of __eq__?


Python, should I implement __ne__() operator based on __eq__?

Short Answer: Don't implement it, but if you must, use ==, not __eq__

In Python 3, != is the negation of == by default, so you are not even required to write a __ne__, and the documentation is no longer opinionated on writing one.

Generally speaking, for Python 3-only code, don't write one unless you need to overshadow the parent implementation, e.g. for a builtin object.

That is, keep in mind Raymond Hettinger's comment:

The __ne__ method follows automatically from __eq__ only if __ne__ isn't already defined in a superclass. So, if you're inheriting from a builtin, it's best to override both.

If you need your code to work in Python 2, follow the recommendation for Python 2 and it will work in Python 3 just fine.

In Python 2, Python itself does not automatically implement any operation in terms of another - therefore, you should define the __ne__ in terms of == instead of the __eq__.E.G.

class A(object):    def __eq__(self, other):        return self.value == other.value    def __ne__(self, other):        return not self == other # NOT `return not self.__eq__(other)`

See proof that

  • implementing __ne__() operator based on __eq__ and
  • not implementing __ne__ in Python 2 at all

provides incorrect behavior in the demonstration below.

Long Answer

The documentation for Python 2 says:

There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected.

So that means that if we define __ne__ in terms of the inverse of __eq__, we can get consistent behavior.

This section of the documentation has been updated for Python 3:

By default, __ne__() delegates to __eq__() and inverts the result unless it is NotImplemented.

and in the "what's new" section, we see this behavior has changed:

  • != now returns the opposite of ==, unless == returns NotImplemented.

For implementing __ne__, we prefer to use the == operator instead of using the __eq__ method directly so that if self.__eq__(other) of a subclass returns NotImplemented for the type checked, Python will appropriately check other.__eq__(self) From the documentation:

The NotImplemented object

This type has a single value. There is a single object with this value. This object is accessed through the built-in name NotImplemented. Numeric methods and rich comparison methods may return this value if they do not implement the operation for the operands provided. (The interpreter will then try the reflected operation, or some other fallback, depending on the operator.) Its truth value is true.

When given a rich comparison operator, if they're not the same type, Python checks if the other is a subtype, and if it has that operator defined, it uses the other's method first (inverse for <, <=, >= and >). If NotImplemented is returned, then it uses the opposite's method. (It does not check for the same method twice.) Using the == operator allows for this logic to take place.


Expectations

Semantically, you should implement __ne__ in terms of the check for equality because users of your class will expect the following functions to be equivalent for all instances of A.:

def negation_of_equals(inst1, inst2):    """always should return same as not_equals(inst1, inst2)"""    return not inst1 == inst2def not_equals(inst1, inst2):    """always should return same as negation_of_equals(inst1, inst2)"""    return inst1 != inst2

That is, both of the above functions should always return the same result. But this is dependent on the programmer.

Demonstration of unexpected behavior when defining __ne__ based on __eq__:

First the setup:

class BaseEquatable(object):    def __init__(self, x):        self.x = x    def __eq__(self, other):        return isinstance(other, BaseEquatable) and self.x == other.xclass ComparableWrong(BaseEquatable):    def __ne__(self, other):        return not self.__eq__(other)class ComparableRight(BaseEquatable):    def __ne__(self, other):        return not self == otherclass EqMixin(object):    def __eq__(self, other):        """override Base __eq__ & bounce to other for __eq__, e.g.         if issubclass(type(self), type(other)): # True in this example        """        return NotImplementedclass ChildComparableWrong(EqMixin, ComparableWrong):    """__ne__ the wrong way (__eq__ directly)"""class ChildComparableRight(EqMixin, ComparableRight):    """__ne__ the right way (uses ==)"""class ChildComparablePy3(EqMixin, BaseEquatable):    """No __ne__, only right in Python 3."""

Instantiate non-equivalent instances:

right1, right2 = ComparableRight(1), ChildComparableRight(2)wrong1, wrong2 = ComparableWrong(1), ChildComparableWrong(2)right_py3_1, right_py3_2 = BaseEquatable(1), ChildComparablePy3(2)

Expected Behavior:

(Note: while every second assertion of each of the below is equivalent and therefore logically redundant to the one before it, I'm including them to demonstrate that order does not matter when one is a subclass of the other.)

These instances have __ne__ implemented with ==:

assert not right1 == right2assert not right2 == right1assert right1 != right2assert right2 != right1

These instances, testing under Python 3, also work correctly:

assert not right_py3_1 == right_py3_2assert not right_py3_2 == right_py3_1assert right_py3_1 != right_py3_2assert right_py3_2 != right_py3_1

And recall that these have __ne__ implemented with __eq__ - while this is the expected behavior, the implementation is incorrect:

assert not wrong1 == wrong2         # These are contradicted by theassert not wrong2 == wrong1         # below unexpected behavior!

Unexpected Behavior:

Note that this comparison contradicts the comparisons above (not wrong1 == wrong2).

>>> assert wrong1 != wrong2Traceback (most recent call last):  File "<stdin>", line 1, in <module>AssertionError

and,

>>> assert wrong2 != wrong1Traceback (most recent call last):  File "<stdin>", line 1, in <module>AssertionError

Don't skip __ne__ in Python 2

For evidence that you should not skip implementing __ne__ in Python 2, see these equivalent objects:

>>> right_py3_1, right_py3_1child = BaseEquatable(1), ChildComparablePy3(1)>>> right_py3_1 != right_py3_1child # as evaluated in Python 2!True

The above result should be False!

Python 3 source

The default CPython implementation for __ne__ is in typeobject.c in object_richcompare:

case Py_NE:    /* By default, __ne__() delegates to __eq__() and inverts the result,       unless the latter returns NotImplemented. */    if (Py_TYPE(self)->tp_richcompare == NULL) {        res = Py_NotImplemented;        Py_INCREF(res);        break;    }    res = (*Py_TYPE(self)->tp_richcompare)(self, other, Py_EQ);    if (res != NULL && res != Py_NotImplemented) {        int ok = PyObject_IsTrue(res);        Py_DECREF(res);        if (ok < 0)            res = NULL;        else {            if (ok)                res = Py_False;            else                res = Py_True;            Py_INCREF(res);        }    }    break;

But the default __ne__ uses __eq__?

Python 3's default __ne__ implementation detail at the C level uses __eq__ because the higher level == (PyObject_RichCompare) would be less efficient - and therefore it must also handle NotImplemented.

If __eq__ is correctly implemented, then the negation of == is also correct - and it allows us to avoid low level implementation details in our __ne__.

Using == allows us to keep our low level logic in one place, and avoid addressing NotImplemented in __ne__.

One might incorrectly assume that == may return NotImplemented.

It actually uses the same logic as the default implementation of __eq__, which checks for identity (see do_richcompare and our evidence below)

class Foo:    def __ne__(self, other):        return NotImplemented    __eq__ = __ne__f = Foo()f2 = Foo()

And the comparisons:

>>> f == fTrue>>> f != fFalse>>> f2 == fFalse>>> f2 != fTrue

Performance

Don't take my word for it, let's see what's more performant:

class CLevel:    "Use default logic programmed in C"class HighLevelPython:    def __ne__(self, other):        return not self == otherclass LowLevelPython:    def __ne__(self, other):        equal = self.__eq__(other)        if equal is NotImplemented:            return NotImplemented        return not equaldef c_level():    cl = CLevel()    return lambda: cl != cldef high_level_python():    hlp = HighLevelPython()    return lambda: hlp != hlpdef low_level_python():    llp = LowLevelPython()    return lambda: llp != llp

I think these performance numbers speak for themselves:

>>> import timeit>>> min(timeit.repeat(c_level()))0.09377292497083545>>> min(timeit.repeat(high_level_python()))0.2654011140111834>>> min(timeit.repeat(low_level_python()))0.3378178110579029

This makes sense when you consider that low_level_python is doing logic in Python that would otherwise be handled on the C level.

Response to some critics

Another answerer writes:

Aaron Hall’s implementation not self == other of the __ne__ method is incorrect as it can never return NotImplemented (not NotImplemented is False) and therefore the __ne__ method that has priority can never fall back on the __ne__ method that does not have priority.

Having __ne__ never return NotImplemented does not make it incorrect. Instead, we handle prioritization with NotImplemented via the check for equality with ==. Assuming == is correctly implemented, we're done.

not self == other used to be the default Python 3 implementation of the __ne__ method but it was a bug and it was corrected in Python 3.4 on January 2015, as ShadowRanger noticed (see issue #21408).

Well, let's explain this.

As noted earlier, Python 3 by default handles __ne__ by first checking if self.__eq__(other) returns NotImplemented (a singleton) - which should be checked for with is and returned if so, else it should return the inverse. Here is that logic written as a class mixin:

class CStyle__ne__:    """Mixin that provides __ne__ functionality equivalent to     the builtin functionality    """    def __ne__(self, other):        equal = self.__eq__(other)        if equal is NotImplemented:            return NotImplemented        return not equal

This is necessary for correctness for C level Python API, and it was introduced in Python 3, making

redundant. All relevant __ne__ methods were removed, including ones implementing their own check as well as ones that delegate to __eq__ directly or via == - and == was the most common way of doing so.

Is Symmetry Important?

Our persistent critic provides a pathological example to make the case for handling NotImplemented in __ne__, valuing symmetry above all else. Let's steel-man the argument with a clear example:

class B:    """    this class has no __eq__ implementation, but asserts     any instance is not equal to any other object    """    def __ne__(self, other):        return Trueclass A:    "This class asserts instances are equivalent to all other objects"    def __eq__(self, other):        return True>>> A() == B(), B() == A(), A() != B(), B() != A()(True, True, False, True)

So, by this logic, in order to maintain symmetry, we need to write the complicated __ne__, regardless of Python version.

class B:    def __ne__(self, other):        return Trueclass A:    def __eq__(self, other):        return True    def __ne__(self, other):        result = other.__eq__(self)        if result is NotImplemented:            return NotImplemented        return not result>>> A() == B(), B() == A(), A() != B(), B() != A()(True, True, True, True)

Apparently we should give no mind that these instances are both equal and not equal.

I propose that symmetry is less important than the presumption of sensible code and following the advice of the documentation.

However, if A had a sensible implementation of __eq__, then we could still follow my direction here and we would still have symmetry:

class B:    def __ne__(self, other):        return Trueclass A:    def __eq__(self, other):        return False         # <- this boolean changed... >>> A() == B(), B() == A(), A() != B(), B() != A()(False, False, True, True)

Conclusion

For Python 2 compatible code, use == to implement __ne__. It is more:

  • correct
  • simple
  • performant

In Python 3 only, use the low-level negation on the C level - it is even more simple and performant (though the programmer is responsible for determining that it is correct).

Again, do not write low-level logic in high level Python.


Yes, that's perfectly fine. In fact, the documentation urges you to define __ne__ when you define __eq__:

There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected.

In a lot of cases (such as this one), it will be as simple as negating the result of __eq__, but not always.


Just for the record, a canonically correct and cross Py2/Py3 portable __ne__ would look like:

import sysclass ...:    ...    def __eq__(self, other):        ...    if sys.version_info[0] == 2:        def __ne__(self, other):            equal = self.__eq__(other)            return equal if equal is NotImplemented else not equal

This works with any __eq__ you might define:

  • Unlike not (self == other), doesn't interfere with in some annoying/complex cases involving comparisons where one of the classes involved doesn't imply that the result of __ne__ is the same as the result of not on __eq__ (e.g. SQLAlchemy's ORM, where both __eq__ and __ne__ return special proxy objects, not True or False, and trying to not the result of __eq__ would return False, rather than the correct proxy object).
  • Unlike not self.__eq__(other), this correctly delegates to the __ne__ of the other instance when self.__eq__ returns NotImplemented (not self.__eq__(other) would be extra wrong, because NotImplemented is truthy, so when __eq__ didn't know how to perform the comparison, __ne__ would return False, implying that the two objects were equal when in fact the only object asked had no idea, which would imply a default of not equal)

If your __eq__ doesn't use NotImplemented returns, this works (with meaningless overhead), if it does use NotImplemented sometimes, this handles it properly. And the Python version check means that if the class is import-ed in Python 3, __ne__ is left undefined, allowing Python's native, efficient fallback __ne__ implementation (a C version of the above) to take over.


Why this is needed

Python overloading rules

The explanation of why you do this instead of other solutions is somewhat arcane. Python has a couple general rules about overloading operators, and comparison operators in particular:

  1. (Applies to all operators) When running LHS OP RHS, try LHS.__op__(RHS), and if that returns NotImplemented, try RHS.__rop__(LHS). Exception: If RHS is a subclass of LHS's class, then test RHS.__rop__(LHS) first. In the case of comparison operators, __eq__ and __ne__ are their own "rop"s (so the test order for __ne__ is LHS.__ne__(RHS), then RHS.__ne__(LHS), reversed if RHS is a subclass of LHS's class)
  2. Aside from the idea of the "swapped" operator, there is no implied relationship between the operators. Even for instance of the same class, LHS.__eq__(RHS) returning True does not imply LHS.__ne__(RHS) returns False (in fact, the operators aren't even required to return boolean values; ORMs like SQLAlchemy intentionally do not, allowing for a more expressive query syntax). As of Python 3, the default __ne__ implementation behaves this way, but it's not contractual; you can override __ne__ in ways that aren't strict opposites of __eq__.

How this applies to overloading comparators

So when you overload an operator, you have two jobs:

  1. If you know how to implement the operation yourself, do so, using only your own knowledge of how to do the comparison (never delegate, implicitly or explicitly, to the other side of the operation; doing so risks incorrectness and/or infinite recursion, depending on how you do it)
  2. If you don't know how to implement the operation yourself, always return NotImplemented, so Python can delegate to the other operand's implementation

The problem with not self.__eq__(other)

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

never delegates to the other side (and is incorrect if __eq__ properly returns NotImplemented). When self.__eq__(other) returns NotImplemented (which is "truthy"), you silently return False, so A() != something_A_knows_nothing_about returns False, when it should have checked if something_A_knows_nothing_about knew how to compare to instances of A, and if it doesn't, it should have returned True (since if neither side knows how to compare to the other, they're considered not equal to one another). If A.__eq__ is incorrectly implemented (returning False instead of NotImplemented when it doesn't recognize the other side), then this is "correct" from A's perspective, returning True (since A doesn't think it's equal, so it's not equal), but it might be wrong from something_A_knows_nothing_about's perspective, since it never even asked something_A_knows_nothing_about; A() != something_A_knows_nothing_about ends up True, but something_A_knows_nothing_about != A() could False, or any other return value.

The problem with not self == other

def __ne__(self, other):    return not self == other

is more subtle. It's going to be correct for 99% of classes, including all classes for which __ne__ is the logical inverse of __eq__. But not self == other breaks both of the rules mentioned above, which means for classes where __ne__ isn't the logical inverse of __eq__, the results are once again non-symmetric, because one of the operands is never asked if it can implement __ne__ at all, even if the other operand can't. The simplest example is a weirdo class which returns False for all comparisons, so A() == Incomparable() and A() != Incomparable() both return False. With a correct implementation of A.__ne__ (one which returns NotImplemented when it doesn't know how to do the comparison), the relationship is symmetric; A() != Incomparable() and Incomparable() != A() agree on the outcome (because in the former case, A.__ne__ returns NotImplemented, then Incomparable.__ne__ returns False, while in the latter, Incomparable.__ne__ returns False directly). But when A.__ne__ is implemented as return not self == other, A() != Incomparable() returns True (because A.__eq__ returns, not NotImplemented, then Incomparable.__eq__ returns False, and A.__ne__ inverts that to True), while Incomparable() != A() returns False.

You can see an example of this in action here.

Obviously, a class that always returns False for both __eq__ and __ne__ is a little strange. But as mentioned before, __eq__ and __ne__ don't even need to return True/False; the SQLAlchemy ORM has classes with comparators that returns a special proxy object for query building, not True/False at all (they're "truthy" if evaluated in a boolean context, but they're never supposed to be evaluated in such a context).

By failing to overload __ne__ properly, you will break classes of that sort, as the code:

 results = session.query(MyTable).filter(MyTable.fieldname != MyClassWithBadNE())

will work (assuming SQLAlchemy knows how to insert MyClassWithBadNE into a SQL string at all; this can be done with type adapters without MyClassWithBadNE having to cooperate at all), passing the expected proxy object to filter, while:

 results = session.query(MyTable).filter(MyClassWithBadNE() != MyTable.fieldname)

will end up passing filter a plain False, because self == other returns a proxy object, and not self == other just converts the truthy proxy object to False. Hopefully, filter throws an exception on being handled invalid arguments like False. While I'm sure many will argue that MyTable.fieldname should be consistently on the left hand side of the comparison, the fact remains that there is no programmatic reason to enforce this in the general case, and a correct generic __ne__ will work either way, while return not self == other only works in one arrangement.