[Tutor] Fwd: calculating a sort key and operator.attrgetter()

Rich Lovely roadierich at googlemail.com
Wed Jul 1 12:31:27 CEST 2009

Forgot to reply-all...

---------- Forwarded message ----------
From: Rich Lovely <roadierich at googlemail.com>
Date: 2009/7/1
Subject: Re: [Tutor] calculating a sort key and operator.attrgetter()
To: Vincent Davis <vincent at vincentdavis.net>

2009/7/1 Vincent Davis <vincent at vincentdavis.net>:
> I have a class with an attribute which is a list "rank_list" this is a list
> of instances f another class that has attributes "quality, is_observed"
> if I want to sort the list by the attribute "quality" I can just use,
> self.rank_list.sort(key=operator.attrgetter('quality'))
> But I want to sort like this.
> self.rank_list.sort(key=(operator.attrgetter('quality') *
> operator.attrgetter('is_observed') * self.does_observe))
> Will this work or is there a better way?
> Thanks
> Vincent Davis
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor

The attrgetter returns a callable, so you'll get e syntax error along
the lines of "You can't multiply two function objects".

As written, it sounds as if self.does_observe will be the same for all
classes within the container, therefore it has no effect on the sort
results.  The only relevant bits are the two attrgetters.

The key argument expects a callable that takes one arguement, and
returns the value to be compared.  Attrgetter returns a function that
takes an object as an argument and gets the attribute named in the
call to the generator.  When you know the name of the attribute you
want in advance, you can get the same effect using a lambda:

operator.attrgetter("is_observed") --> lambda o: o.is_observed

There are two ways to do what you're after:
1. Define a new function (This can be inside the function that does
the sorting, or higher if it's needed elsewhere)

def keyFunc(o):
   """returns a sort key for object o"""
   return o.quality * o.is_observed


2. use a lambda:

self.rank_list.sort(key=(lambda o: o.quality * o.is_observed))

If you want a reusable solution, method 1 is better.  If you want a
simple, easy to read, solution, 2 is probably better.  If there is a
chance of the wrong sort of class getting into the list, you'll need
to use 1 if you want to use error handling, as you can't use try and
except in a lambda.

Richard "Roadie Rich" Lovely, part of the JNP|UK Famile

Richard "Roadie Rich" Lovely, part of the JNP|UK Famile

More information about the Tutor mailing list