[Python-Dev] operator precedence of eq, ne, etc, if both object have implementations (original) (raw)

Guido van Rossum guido at python.org
Wed Sep 23 22:22:31 CEST 2009


All,

I don't have the bandwidth right now to help out much in this thread, so I'm glad that the collective effort has mostly figured out what the rules are (as well as what they should be :-). It truly is a mess, mostly thanks to the various concerns for backwards compatibility (classic vs. new classes and cmp vs rich comparisons makes for a truly maddening compatibility matrix).

The double eq calls in the pastebin examples are a surprise even to me; it seems the logic for first giving the left object a chance and then the right object is duplicated in the generic rich comparison logic in object.c and again in instance_richcompare() in classobject.c.

As Brett cautioned in the bug, I would be hesitant to try and fix this in 2.x; there's simply too much code that relies on whatever odd behavior CPython happens to exhibit, especially in test suites that often over-constrain the behavior (see e.g. the other thread about error messages, where I have nothing to add that Brett didn't already say). In 3.2 I'm fine with the (ever so slight) semantic change, especially since the behavior will rarely be exhibited in practice. (You'd have to have two different objects with eq methods that return NotImplemented and have some kind of side effect that is expected.)

--Guido

On Tue, Sep 22, 2009 at 8:12 AM, Mark Dickinson <dickinsm at gmail.com> wrote:

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, slottprichcompare (in typeobject.c) makes two calls to halfrichcompare;  I think the second is redundant.  The coercion rules are already taken care of in dorichcompare (in object.c).  I tried removing the second call to halfrichcompare, 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


Python-Dev mailing list Python-Dev at python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/guido%40python.org

-- --Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-Dev mailing list