__eq__ and __ne__

Tim Peters tim at zope.com
Tue Jul 8 11:54:52 EDT 2003


[Shane Hathaway]
> I was surprised by the following behavior.  Apparently, the "!="
> operator does not fall back to using "not __eq__()".

That's true -- there are no magical equivalences among the six rich
comparison operators.

> I tested this with Python 2.1, 2.2, and 2.2 with new-style classes and
> got the same results in every case.

Whew!  I was afraid a bug may have slipped in <wink>.

>  >>> class foo:
> ...     def __eq__(self, other):
> ...         return (other.__class__ is self.__class__
> ...                 and other.__dict__ == self.__dict__) ...
>  >>> foo() == foo()
> 1
>  >>> foo() != foo()
> 1
>
> I would expect the second test to yield "0".  To compensate, I've
> started adding the following boilerplate code to all classes that
> define only __eq__:
>
> def __ne__(self, other):
>      return not self.__eq__(other)

That's appropriate if that's what you what "!=" to mean.

> Does this surprise anyone else?  I have not yet found documentation
> on this.

The language (not library) Ref Man says this (under "Basic Customization"),
and means what it says:

    The correspondence between operator symbols and method names is as
    follows:  x<y calls x.__lt__(y), x<=y calls x.__le__(y), x==y
    calls x.__eq__(y), x!=y and x<>y call x.__ne__(y), x>y calls
    x.__gt__(y), and x>=y calls x.__ge__(y).

In the richcmp PEP:

    http://www.python.org/peps/pep-0207.html

point 3 under "Proposed Resolutions" gives one rationale:

    3 The == and != operators are not assumed to be each other's
      complement (e.g. IEEE 754 floating point numbers do not satisfy
      this).  It is up to the type to implement this if desired.
      Similar for < and >=, or > and <=; there are lots of examples
      where these assumptions aren't true (e.g. tabnanny).

A more involved (and probably more basic) rationale has to do with that the
richcmp operators aren't constrained to return Boolean results; as the PEP
says at its start:

    The main motivation comes from NumPy, whose users agree that A<B
    should return an array of elementwise comparison outcomes;

Since the richcmp operators aren't constrained to return scalars, an attempt
to define one in terms of the others seemed futile.  Instead they're 6
independent methods.






More information about the Python-list mailing list