[Python-Dev] operator precedence of __eq__, __ne__, etc, if both object have implementations

Mark Dickinson dickinsm at gmail.com
Wed Sep 23 13:05:31 CEST 2009


On Wed, Sep 23, 2009 at 9:12 AM, Chris Withers <chris at simplistix.co.uk> wrote:
> Mark Dickinson wrote:
>>
>> I (still :-) think this is covered, for Python 2.x at least, by:
>>
>> http://docs.python.org/reference/datamodel.html#coercion-rules
>
> But this isn't coercion! :-)

Agreed.  FWIW this behaviour for arithmetic operations is also mentioned in

http://docs.python.org/reference/datamodel.html#emulating-numeric-types

but then again that section doesn't include the comparison operators.

>
>> - For objects x and y, first x.__op__(y) is tried. If this is not
>> implemented or returns NotImplemented, y.__rop__(x) is tried.
>
> Also, the above is not so:
>
> Python 2.5.1
>>>> class X:
> ...   def __eq__(self,other):
> ...     print "X __eq__"
>>>> class Z: pass
> ...
>>>> Z()==X()
> X __eq__
>
> No __req__ in sight...

Okay, so combine this with the sentence under:

http://docs.python.org/reference/datamodel.html#object.__eq__

that says:

"There are no swapped-argument versions of these methods (to be used
when the left argument does not support the operation but the right
argument does); rather, __lt__() and __gt__() are each other’s
reflection, __le__() and __ge__() are each other’s reflection, and
__eq__() and __ne__() are their own reflection."

So in the earlier doc snippets, if __op__ is __eq__, then __rop__
should also be interpreted as __eq__;  similarly if __op__ is __lt__
then __rop__ is __gt__.

I'm not saying that the documentation here couldn't be improved;  just
that IMO the docs do (with a little bit of extrapolation) describe
what should happen, giving the 'official' specification that you were
after.

I don't know where/whether the behaviour for classes that define both
__cmp__ and __eq__ are documented, though, and I'm far from sure what
the rules are in that case.

One minor oddity is that for arithmetic operations like __add__(self,
other), if type(self) == type(other) then __radd__ isn't checked, on
the basis that if __add__ fails then the operation is presumably not
supported.  This makes sense, but I wonder why this doesn't apply
equally well to __eq__:  that is, in doing A() == A() for a class A,
why do we try the __eq__ method of both instances?

Mark


More information about the Python-Dev mailing list