So far, we've been using the "key" parameter of list.sort. If you want sort criteria more complicated than a single attribute, you can sort based on a custom comparison function.
Actually, the key= parameter can do anything the cmp= parameter can:
class Key(object): def __init__(self, item) self.item = item def __cmp__(self, other): # put your usual cmp code here cmp(self.item, other) lst.sort(key=Key)
Of course this is a pretty silly way to write a cmp function. But the point is that you shouldn't think of the key= parameter as only useful for simple comparisons. See
http://mail.python.org/pipermail/python-list/2005-April/277448.html
for a recent example of a pretty complex key function.
I would guess that 80-90% of all uses of sort that need a custom comparison function can be met easily by using the key= parameter and will be more efficient than using the cmp= parameter.
The above "Key" example has the same inefficiency problems that the cmp= parameter normally does, but in most cases, you won't need to define a custom __cmp__ function, and you can rely on __cmp__ functions implemented in C, like those of strs and tuples (as I do below).
So another way to do a sort-by-author for your books would be:
def compare_authors(book1, book2): return cmp(book1.author, book2.author)
books.sort(compare_authors)
This is definitely not a case where you want to use a comparison function. It will be much more efficient to write:
def author_key(book): return book.author books.sort(key=author_key)
A more complicated comparison function might nest two others:
def compare_dates(book1, book2): # Assuming that your dates are either numerical or are strings for which # alphabetical sorting is identical to chronological... return cmp(book1.date, book2.date)
def compare_author_and_date(book1, book2):
different_authors = compare_authors(book1, book2)
if different_authors: # different authors
return different_authors
else: # same author. sort by date.
return compare_dates(book1, book2)
books.sort(compare_author_and_date)
Likewise, the above is basically just an inefficient way of writing:
def date_key(book): return book.data
def author_and_date_key(book): return (author_key(book), date_key(book))
books.sort(key=author_and_date_key)
Note that the thing I take advantage of here is that tuples are comparable, and compare as you'd expect them to (in lexicographic order).
STeVe -- http://mail.python.org/mailman/listinfo/python-list