[Python-Dev] decorate-sort-undecorate

Geoffrey Talvola gtalvola at nameconnector.com
Tue Oct 14 17:06:19 EDT 2003


Tim Peters wrote:
> [Geoffrey Talvola]
>> I disagree... I almost always use DSU in any circumstances because I
>> find it easier and more natural to write:
>> 
>> def keyfunc(record):
>>     return record.LastName.lower(), record.FirstName.lower(),       
>> record.PhoneNumber mylist = sortUsingKeyFunc(mylist, keyfunc)
> 
> You've left out the body of sortUsingKeyFunc, so I expect
> you're unusual in
> having built up helper routines for doing DSU frequently.
> 

Yes, I do use a helper routine, but I suspect I'm not the only one out there
who does...

>> than to have to write an equivalent comparison function:
>> 
>> def cmpfunc(r1, r2):
>>     return cmp((r1.LastName.lower(), r1.FirstName.lower(),
>>                r1.PhoneNumber), (r2.LastName.lower(),
>>                r2.FirstName.lower(), r2.PhoneNumber))
>> mylist.sort(cmpfunc)
> 
> This is wordier than need be, though, duplicating code for
> the purpose of
> making it look bad <wink>.  I'd do
> 
> mylist.sort(lambda a, b: cmp(keyfunc(a), keyfunc(b)))

I'm not a huge fan of lambdas from a readability perspective, so I'd
probably wrap _that_ up into a helper function if I didn't know about DSU.

The point I'm trying to make it that a key function is usually more natural
to use than a comparison function.  You're right, DSU isn't the only way to
make use of a key function.  But, I think it would be a good thing for
list.sort() to take a key function because it will guide users toward using
the cleaner key function idiom and therefore improve the readability of
Python code everywhere.

> 
>> so for me, ease of use is the reason, not speed.  Of course, it
>> doesn't _hurt_ that DSU is faster...
> 
> If your records often tie on the result of keyfunc (doesn't
> look likely
> given the names you picked here), and your sortUsingKeyFunc() function
> doesn't inject the original list index (or otherwise force a cheap
> tie-breaker), DSU can be much slower than passing a custom comparison
> function.  Not likely, though.

Not to worry, I do inject the original list index.  For the record, here's
my helper function, probably not optimally efficient but good enough for me:

def sortUsingKeyFunc(l, keyfunc):
    l = zip(map(keyfunc, l), range(len(l)), l)
    l.sort()
    return [x[2] for x in l]

- Geoff



More information about the Python-Dev mailing list