2

As far as I can tell the only difference is speed and you have to be a bit tricker in how you define lambda functions.

For instance:

map(lambda x: x + 1, range(4)) == [(lambda x: x + 1)(y) for y in range(4)]

It seems to me like the second way is more pythonic, but I am not sure why.

EDIT:

Yes I understand that the lambda would be excluded in the second example, I was just trying to show as equivalent code as possible.

placeybordeaux
  • 2,138
  • 1
  • 20
  • 42

2 Answers2

6

The right way to do this would be

[y + 1 for y in range(4)]

No need to construct a lambda function here. Your code would unnecessarily build a new function object in every single iteration of the list comprehension.

That said, you can write any call to map() as an equivalent list comprehension. If the first argument to map() is a lambda function, the list comprehension is usually preferred. If the first argument to map() is a function name, both variants are fine. Some people (including me) prefer, say,

map(str, my_list)

while others prefer

[str(x) for x in my_list]
amcnabb
  • 2,161
  • 1
  • 16
  • 24
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Though if you were adding on some conditionals, the map would then need a lambda, right? `[y + 1 for y in range(4) if y > 2]` – jdi Mar 23 '12 at 17:31
  • @jdi: The call to `map()` always needs a `lambda` function for this case, doesn't it? (Unless you resort to obfuscated code like `map(1 .__add__, range(4))`, that is.) – Sven Marnach Mar 23 '12 at 17:33
  • @SvenMarnach That wouldn't be syntactically valid (you need brackets), but I think that is kind of a nice way of expressing that. – Marcin Mar 23 '12 at 17:35
  • 3
    @Marcin: This runs in my interpreter. (Note the space after `1` which is indeed needed.) – Sven Marnach Mar 23 '12 at 17:35
  • I think I was just mixing up various parts of your answer in my head lol. It was the 'no need for a lambda' part mixed with anything that can be written with a map can also be written with a list comp. So I was just commenting on the equivalent map for that list comp needing a lamba as opposed to an existing named callable or something. Im babbling. – jdi Mar 23 '12 at 17:36
  • 4
    `map` is especially nice when you want to call a function that takes multiple arguments. I prefer `map(func, a, b)` to `[func(*args) for args in zip(a, b)]` – Steven Rumbalski Mar 23 '12 at 17:42
3

There is no difference, but the pythonic way would be to omit the lambda completely:

[y + 1 for y in range(4)]

Note also that if your mapping function is a "built-in" (written in C) function, rather than a python function or a lambda, map will be faster.

Another pythonic, but uncommon, way (avoids unnecessary lambda) would be:

map(1 .__add__, range(4)) # thanks to SvenMarnach for this

It is usually preferable to avoid lambdas in mapping forms, because a list comprehension will always be more efficient, AND clearer. By contrast, using multi-line functions is perfectly acceptable - there is no way to write them inline, and even if you could, it would likely be less clear.

Another difference is that because map can take multiple sequences to map against, and passes them as positional parameters to the mapping function, one can avoid the zipping that would be required in a list comprehension:

[x+y for x,y in zip(range(4), range(2,6))]
#vs
from operator import add
map(add, range(4), range(2,6))
Marcin
  • 48,559
  • 18
  • 128
  • 201
  • As a side note, in python 3 maps will create iterators and not lists, so be careful of that as you move forward with the language. – Bryce Mar 23 '12 at 17:38
  • *"`map` may be microscopically faster in some cases (when you're NOT making a lambda for the purpose, but using the same function in map and a listcomp). List comprehensions may be faster in other cases [...]"* - from [here](http://stackoverflow.com/a/1247490/1132524) – Rik Poggi Mar 23 '12 at 17:41
  • @RikPoggi True, but only in the case of built-in functions. Python functions all suffer from the same performance hit. – Marcin Mar 23 '12 at 17:43
  • is "map(1 .__add__, range(4))" truly pythonic? – placeybordeaux Mar 23 '12 at 18:47
  • @placeybordeaux It's concise, explicit, and comprehensible – Marcin Mar 24 '12 at 08:00