[Tutor] Python Cookbook

Yigal Duppen yduppen@xs4all.nl
Mon, 26 Aug 2002 15:54:55 +0200


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

> can now be done much more elegantly as:
>
>    def method(self, argument, *args, **kw):
>      # Do something with argument
>      callable(*args, *kw)
>
> """
>
> This must be a new form of callable(), because in my copy of Python
> Essential Reference (for 2.1), callable() takes one parameter argument
> that is an object.

I believe that 'callable' here does not refer to the builtin 'callable' 
function, but instead serves as a placeholder for any callable object (i.e. 
any x for which 'callable(x)' is true). 

Not very clear, I agree.

> I understood what map() and filter() do, but why are list comprehensions
> better?  FWIW, I don't really know exactly what a list comprehension is,
> only that PER says that the following
>
>    map(function, alist)
>
> can be better written using list comprehension as
>
>    [function(x) for x in alist]
>
> -- why?

In my case, the best reason for doing this is when you want to map methods on 
a set of objects.

Example: 

class Foo:
	def __init__(self, x):
		self.x = x

	def getX(self):
		return self.x

A fairly simple class, which only serves as an example.
Now let's build a list of Foo objects:

l = [ Foo(1), Foo(2), Foo(3), Foo(4), Foo(5), Foo(6) ]

Now imagine I need a derived list, containing the value of all getX methods. 
Using map, there are two possible ways of doing this:

derived = map(Foo.getX, l)

or 

derived = map(lambda z: z.getX(), l)

The first case only works if you're sure that the list l only contains objects 
of class Foo; if there are subclasses of Foo with an overridden method getX, 
the first example doesn't work.

The second case requires constructing a new anonymous function; while I 
usually have no problem with lambdas, it seems that many people do. 

List comprehensions (LCs) provide a much better way of getting the derived 
list:
derived = [ z.getX() for z in l ]

As you can see, this requires no anonymous functions and is perfectly OO.

The advantage of this becomes even clearer if you want to map AND filter. 
Let's say we only want the even values and that we have no 'odd' or 'even' 
function. 

derivedEven = filter(lambda n: n % 2 == 0, map(lambda z: z.getX(), l))

Argl! What does this do? All we have is the 'descriptive' variable name. 

derivedEven = [ z.getX() for z in l if z.getX() % 2 == 0 ]

Much better! But then again, LCs are also a matter of taste :)

YDD
- -- 
http://www.xs4all.nl/~yduppen
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)

iD8DBQE9ajMwLsKMuCf5EdwRAsqwAKC0swPYqe9Bw+aMz9C0kdbnDwPS7wCg+kdP
5st8sTJ3nn54ReKRfafx0N8=
=43il
-----END PGP SIGNATURE-----