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

Mark Dickinson dickinsm at gmail.com
Tue Sep 22 17:12:32 CEST 2009


On Tue, Sep 22, 2009 at 3:37 PM, Chris Withers <chris at simplistix.co.uk> wrote:
> Where are the specifications on what happens if two objects are compared and both have implementations of __eq__? Which __eq__ is called?
> What happens if the first one called returns False? Is the second one called? What is one implements __eq__ and the other __ne__?

I (still :-) think this is covered, for Python 2.x at least, by:

http://docs.python.org/reference/datamodel.html#coercion-rules

Specifically, the bits that say:

- For objects x and y, first x.__op__(y) is tried. If this is not
implemented or returns NotImplemented, y.__rop__(x) is tried. If this
is also not implemented or returns NotImplemented, a TypeError
exception is raised. But see the following exception:

- Exception to the previous item: if the left operand is an instance
of a built-in type or a new-style class, and the right operand is an
instance of a proper subclass of that type or class and overrides the
base’s __rop__() method, the right operand’s __rop__() method is tried
before the left operand’s __op__() method.

I agree that having these rules in a section called 'Coercion rules'
is a bit confusing.

> Python 2
> http://pastebin.com/f8f19ab3
>
> Python 3
> http://pastebin.com/f55e44630

The duplicate __eq__ calls in these pastes are disturbing:  in short,
if A() and B() are new-style classes defining __eq__, it seems that
A() == B() ends up calling A.__eq__ twice *and* B.__eq__ twice, in the
order A.__eq__, B.__eq__, B.__eq__, A.__eq__.

In 3.x, slot_tp_richcompare (in typeobject.c) makes two calls to
half_richcompare;  I think the second is redundant.  The coercion
rules are already taken care of in do_richcompare (in object.c).  I
tried removing the second call to half_richcompare, and the entire
test-suite still runs without errors.

In 2.x, it's possible that this call is necessary for some bizarre
combinations of __cmp__ and __eq__;  I haven't tried to get my head
around this yet.

I'll open an issue for the duplicate __eq__ calls.

Mark


More information about the Python-Dev mailing list