[Tutor] True and 1 [was Re: use of the newer dict types]

eryksun eryksun at gmail.com
Wed Jul 31 16:16:52 CEST 2013


On Mon, Jul 29, 2013 at 7:33 AM, Albert-Jan Roskam <fomcl at yahoo.com> wrote:
> Wow, too bad __cmp__ is no longer present. Not so much for cmp(), but
> because it's such a compact way to define all the comparison methods.
> Btw, my book says "Python will supply the __ne__() (not equal)
> inequality operator automatically if wel implement __eq__ but don't
> implement __ne__()". [Programming in Python 3 (2009), M. Summerfield,
> p.213]

That's true in 3.x. The base object type has a default rich comparison
that uses __eq__ to implement __ne__ (but not vice versa).

The CPython tp_richcompare slot function is object_richcompare in
Objects/typeobject.c. Here's a link to 3.3.2:

http://hg.python.org/cpython/file/d047928ae3f6/Objects/typeobject.c#l3175

In 2.x the base object type doesn't implement rich comparisons. You'll
get the default comparison in CPython (by id or type name), which
won't necessarily be consistent with __eq__.

Here's something to riddle out. Why does CPython 2.x make 22 method
calls for the following cmp()?

    class A(object):
        def _print(self, op):
            print '%s.__%s__' % (type(self).__name__, op)
        def __eq__(self, other):
            self._print('eq')
            return NotImplemented
        def __lt__(self, other):
            self._print('lt')
            return NotImplemented
        def __gt__(self, other):
            self._print('gt')
            return NotImplemented
        def __coerce__(self, other):
            self._print('coerce')
            return NotImplemented

    class B(A):
        pass

    >>> cmp(A(), B())
    B.__eq__
    A.__eq__
    A.__eq__
    B.__eq__
    B.__eq__
    A.__eq__
    B.__gt__
    A.__lt__
    A.__lt__
    B.__gt__
    B.__gt__
    A.__lt__
    B.__lt__
    A.__gt__
    A.__gt__
    B.__lt__
    B.__lt__
    A.__gt__
    A.__coerce__
    B.__coerce__
    B.__coerce__
    A.__coerce__
    -1

Why is the order BAABBA repeated 3 times? As a hint, I'll group it
like this: BA--AB--BA.

Jython does this 'right' (IMHO) with 8 calls. PyPy appears to be
playing tight to what's technically allowed and steps over the line.
It only uses 4 calls, but it doesn't attempt a __coerce__, which I
think is technically wrong.


More information about the Tutor mailing list