« No natural predator but your imagination | Main | Python preinstalled on ThinkPad »

map() and list comprehensions

It looks likely that the lisp-style functions in Python such as map() will be removed, (along with lambda). The arguments for doing this seem to come down to two things: that you can use list comprehensions to provide the same functionality, and, that people don't like Lispisms (ie introducing them into Python way back when was a mistake that needs to be rectified). Various incidental arguments around speed also come up, but they don't matter.

I never fully understood the excitement around list comps when they were introduced. I suspect that because you can see just enough of the innards, a list comp is impressive, a bit like having a glass hood over a car engine or a perspex kettle. On the other hand , map() is opaque, even dull.

I imagine I like the map() approach because functions tend to nest and compose more elegantly than extra syntax. Removing top-level functions like map() from Python in favor of list comps fees like a step backwards. I don't see is how this:

  mods = [__import__(mod) for mod in testmodules]

is ever going to be more elegant than this:

  mods = map(__import__, testmodules)

March 28, 2005 10:43 PM

Comments

Robert Sayre
(March 28, 2005 11:50 PM #)

pgs 437-438 of Text Processing In Python cover this pretty well. List comps are probably better if you're just looking to eliminate nested loops. If you're actually composing functions, I'm not so sure.

Bill de hra
(March 29, 2005 01:08 AM #)

(runs upstairs to get the Mertz book...) Indeed it does cover it. Thanks for the pointer.

For loops do take up a lot of space. I remember a colleague and I looking at a codebase once and guesstimating that ~25% of the code would disappear if map() or list comps were used.

I suppose nesting functions is Lisponic, but not Pythonic. Or something like that.

Patrick Logan
(March 29, 2005 02:09 AM #)

I'm not familiar with comprehensions in Python. If you look at Erlang, Haskell, etc. then comprehensions can be as expressive as a query language using joins, etc. i.e. more than one list can be in the comprehension, comparing elements, and projecting values based on elements, from each list.

Ian Bicking
(March 29, 2005 02:52 AM #)

This has definitely not been my experience. For instance, [s.lower() for s in lst] is way better than map(lambda s: s.lower(), lst) -- the Lispy functions just don't work well with methods and OO conventions.

I don't really see the composition as any better either. Is this: map(lambda s: s.lower(), map(str, lst)) better than [str(s).lower() for s in lst] ?

Victor Yang
(March 29, 2005 03:37 AM #)


I just wonder why Python can't keep both syntax. Anyway, it is just syntax. However I like map(func,list) since explicitly expressing a loop over the list makes it a bit verbose.

Robert Sayre
(March 29, 2005 04:21 PM #)

Ian,

that's kind of a setup. If you've got functions assigned to free variables, it works better:

map(string.lower, map(str, lst))

Rich Salz
(March 29, 2005 07:11 PM #)

It's the "if" part of listcomps that make it more powerful than map. I suppose map() becomes a lambda for a listcomp now? :)

Brandon Corfman
(March 30, 2005 02:11 PM #)

For people that refactor their initial for-loops into a reduced form like map or a listcomp, I think the listcomp wins because it's easier to see how to refactor into that form as opposed to map (most of the time). See this post for an example.

Of course, if you come from a Lisp background, this statement probably isn't true.

OderWat
(November 9, 2005 02:52 PM #)

I just had to think about this because of pylint...

', '.join([a[0] for a in d])

is really nicer and easier to understand than

', '.join(map(lambda a:(a[0]),d))