Python 3 __cmp__ semantic change?

Arnaud Delobelle arnodel at googlemail.com
Sat Nov 22 04:10:04 EST 2008


Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> writes:

> On Sat, 22 Nov 2008 08:27:59 +0000, Arnaud Delobelle wrote:
>
>>>> Granted it's not as efficient as a __cmp__ function.
>>>
>>> What makes you say that? What do you mean by "efficient"? Are you
>>> talking about memory footprint, runtime speed, disk-space, programmer
>>> efficiency, algorithmic complexity, or something else?
>> 
>> What I'm talking about is very simple - and explained below, with the
>> help of your __cmp__ method.
>>>
>>> As I see it, a __cmp__ method would be written something like this:
>>>
>>>     def __cmp__(self, other):
>>>         return cmp(self.num*other.den, self.den*other.num)
>> 
>> I'm talking about runtime speed (*not* asymptotic complexity).  My code
>> makes Fraction.__gt__ about twice as slow as Fraction.__lt__ or
>> Fraction.__eq__ even though with __cmp__ they would all be equally fast.
>
>
> Sounds like a premature micro-optimization to me. On my machine, running 
> Python 2.5, the speed difference is nothing like twice as slow.
>
>
>>>> class UseCmp(object):
> ...     def __init__(self, num, den=1):
> ...             self.num = num
> ...             self.den = den
> ...     def __cmp__(self, other):
> ...             return cmp(self.num*other.den, self.den*other.num)
> ...
>>>> class UseRichCmp(UseCmp):
> ...     __lt__ = lambda self, other: self.__cmp__(other) < 0
> ...
>>>> from timeit import Timer
>>>> t1 = Timer('x < y',
> ... 'from __main__ import UseCmp; x=UseCmp(3, 5); y=UseCmp(1, 2)')
>>>> t2 = Timer('x < y',
> ... 'from __main__ import UseRichCmp;'
> ... 'x=UseRichCmp(3, 5); y=UseRichCmp(1, 2)')
>>>>
>>>> t1.repeat()
> [3.3418200016021729, 2.4046459197998047, 2.2295808792114258]
>>>> t2.repeat()
> [3.8954730033874512, 3.0240590572357178, 3.5528950691223145]
>
> There's a slight speed difference, around 35% slower. But the random 
> variation in speed is almost 50%, so I would conclude from this trial 
> that there is no *significant* speed difference between the methods.

That's not surprising.  You're measuring the wrong things.  If you read
what I wrote, you'll see that I'm talking about Fraction.__gt__ being
slower (as it is defined in terms of Fraction.__eq__ and
Fraction.__lt__) using when my 'totally_ordered' decorator.

I haven't done any tests but as Fraction.__gt__ calls *both*
Fraction.__eq__ and Fraction.__lt__ it is obvious that it is going to be
roughly twice as slow.

-- 
Arnaud



More information about the Python-list mailing list