[Python-ideas] Automatic total ordering

George Sakkis george.sakkis at gmail.com
Wed Oct 15 23:36:56 CEST 2008


On Wed, Oct 15, 2008 at 4:50 PM, Arnaud Delobelle <arnodel at googlemail.com>wrote:

>
> On 15 Oct 2008, at 19:35, George Sakkis wrote:
>
>  On Wed, Oct 15, 2008 at 2:11 PM, Guido van Rossum <guido at python.org>
>> wrote:
>>
>> On Wed, Oct 15, 2008 at 11:03 AM, Terry Reedy <tjreedy at udel.edu> wrote:
>> > George Sakkis wrote:
>> >>
>> >> Now that 3.x fixes the arbitrary object comparison wart and drops (?)
>> >> __cmp__,
>> >
>> > An entry for __cmp__ was in the 3.0c1 doc, which confused me.
>> > It is now gone in
>> >
>> http://docs.python.org/dev/3.0/reference/datamodel.html#special-method-names
>> >
>> > Since rich comparisons are defined on object and are inherited by all
>> > classes, it would be difficult to make them not defined.
>>
>> I should also note that part of George's proposal has already been
>> implemented: if you define __eq__, you get a complementary __ne__ for
>> free. However it doesn't work the other way around (defining __ne__
>> doesn't give you __eq__ for free), and there is no similar
>> relationship for the ordering operators. The reason for the freebie is
>> that it's *extremely* unlikely to want to define != as something other
>> than the complement of == (the only use case is IEEE compliant NaNs);
>> however it's pretty common to define non-total orderings (e.g. set
>> inclusion).
>>
>> Partial orderings are certainly used, but I believe they are far less
>> common than total ones. Regardless, a partially ordered class has to
>> explicitly define the supported methods with the desired semantics anyway;
>> the proposed change wouldn't make this any harder.
>>
>
> I don't understand.  In a mathematical ordering,
>
> * x > y means the same as y < x
> * x <= y means the same as x < y or x = y
> * x >= y means the same as x > y or x = y
>
> and this is irrespective of whether the ordering is partial or total.
>
> So, given __eq__ and __lt__, all the rest follows. E.g.
>
> def __gt__(self, other):
>    return other.__lt__(self)
> etc...
>
> Where am I going wrong?


For total orderings, one can define all methods in terms of self.__eq__ and
self.__lt__, i.e. avoid making any assumption about `other`, e.g:

def __gt__(self, other):
   return not (self == other or self < other)

Your __gt__ definition (which is also what Michael Foord does in his class
decorator) may break mysteriously:

    class Thing(object):
        def __init__(self, val):
            self.val = val

    @total_ordering
    class Thing_lt(Thing):
        def __lt__(self, other):
            return self.val < other.val

    >>> t1 = Thing_lt(1)
    >>> t2 = Thing(2)
    >>> t1 < t2
    True
    >>> t1 > t2
    ...
    RuntimeError: maximum recursion depth exceeded


George
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20081015/ffb58347/attachment.html>


More information about the Python-ideas mailing list