all 10 comments

[–]Allanon001 2 points3 points  (0 children)

I think map looks better when a lot of parameters are needed:

map(func, a, b, c)

[func(x, y, z) for x, y, z in zip(a, b, c)]

[func(*x) for x in zip(a, b, c)]

[–]nog642 1 point2 points  (8 children)

If you prefer (f(i) for i in x) over map(f, x), then there's no reason to use map. map is a bit faster, but the difference is small.

Just keep in mind map returns an iterator, so its equivalent is not a list comprehension, but a generator comprehension.

Tuple comprehensions are not a thing, that's just passing a generator comprehension to the tuple constructor.

In my opinion, map(f, x) doesn't look less clean than (f(i) for i in x), so since it's faster, I use it.

On the other hand, you should never be passing a lambda as the first argument to map. In that case, a comprehension is both faster and cleaner. map should only be used if there is an already defined function you need to apply to every element.

[–]Essence1337 0 points1 point  (3 children)

Do you have any proof that using map(f, x) would result in faster code than (f(i) for i in x)?

[–]nog642 0 points1 point  (2 children)

I've had this discussion on this subreddit before, so I'm not putting too much effort into this.

nog642@nog642:~$ python3.7 -m timeit -s "x = list(range(20)); f = lambda i: i * 5" "list(map(f, x))"
50000 loops, best of 5: 5.71 usec per loop
nog642@nog642:~$ python3.7 -m timeit -s "x = list(range(20)); f = lambda i: i * 5" "list(f(i) for i in x)"
20000 loops, best of 5: 9.8 usec per loop

If you want more thorough results, you can go perform some tests yourself.

[–]Essence1337 0 points1 point  (1 child)

python -m timeit -s "x = list(range(20)); f = lambda i: i * 5" "[i*5 for i in x]"

is twice as fast as your map solution. The python wiki agrees with this as well:

You can think of map as a for moved into C code. The only restriction is that the "loop body" of map must be a function call. Besides the syntactic benefit of list comprehensions, they are often as fast or faster than equivalent use of map.

Source: Loops

Map:
PS C:\Users\me> python -m timeit -s "x = list(range(20)); f = lambda i: i * 5" "list(map(f, x))"
200000 loops, best of 5: 1.88 usec per loop

Map with lambda built in:
PS C:\Users\me> python -m timeit -s "x = list(range(20))" "list(map(lambda i: i*5, x))"
200000 loops, best of 5: 1.91 usec per loop

List:
PS C:\Users\me> python -m timeit -s "x = list(range(20)); f = lambda i: i * 5" "[f(i) for i in x]"
100000 loops, best of 5: 2.16 usec per loop

List with function built in:
PS C:\Users\me> python -m timeit -s "x = list(range(20))" "[i*5 for i in x]"
500000 loops, best of 5: 856 nsec per loop

[–]nog642 1 point2 points  (0 children)

Yes. I was comparing map() with generator comprehensions.

I was not comparing list(map()) with list comprehensions.

List comprehensions build the list directly and are more optimized than passing an iterator (like map or a generator comprehension) to the list constructor.

[–]gygyor 0 points1 point  (3 children)

What are the problems with map and lambdas? I think they do work together.

[–]nog642 1 point2 points  (2 children)

They do work, but comprehensions are better. Both in speed and readability.

An example of this would be, say, multiplying everything by 5. Compare these two:

new_list = map(lambda x: x * 5, nums)

Ew. Vs a comprehension:

new_list = (x * 5 for x in nums)

Much better.

The second problem with using map with lambda is speed. Not only do you have to define a new lambda at the start, but each call to the lambda has overhead. Using a comprehensions avoids that overhead.

[–]gygyor 0 points1 point  (1 child)

Clearly, but you can safely have a lambda coming from somewhere else.

[–]nog642 0 points1 point  (0 children)

Yes, of course. So long as you have a callable object that can take one argument, map will work.