List Comprehension VS Map

List comprehension vs map

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 and most (not all) pythonistas consider them more direct and clearer.

An example of the tiny speed advantage of map when using exactly the same function:

$ python -m timeit -s'xs=range(10)' 'map(hex, xs)'
100000 loops, best of 3: 4.86 usec per loop
$ python -m timeit -s'xs=range(10)' '[hex(x) for x in xs]'
100000 loops, best of 3: 5.58 usec per loop

An example of how performance comparison gets completely reversed when map needs a lambda:

$ python -m timeit -s'xs=range(10)' 'map(lambda x: x+2, xs)'
100000 loops, best of 3: 4.24 usec per loop
$ python -m timeit -s'xs=range(10)' '[x+2 for x in xs]'
100000 loops, best of 3: 2.32 usec per loop

Map vs List vs loop in python 3.7

First of all, to have a fare comparison you have to convert the result of the map function to list. map in Python 3.X returns an iterator object not a list. Second of all, in CPython implementation built in functions are actually wrappers around c functions which makes them faster than any Python code with same functionality, although when you use lambda inside a built-in function you're actually breaking the chain and this will make it approximately as fast as a Python code.

Another important point is that list comprehension is just a syntactic sugar around a regular loop and you can use it to avoid extra function calls like appending to lists, etc.

Python: List Comprehensions vs. map

All your timing results can be explained by theses facts:

  1. CPython has a rather high function call overhead.

  2. map(f, it) is slightly faster than [f(x) for x in it].

The first version of your code does not define a function at all, so there is no function call overhead. The second version needs to define a function, ,so there is function call overhead in every iteration. The third version is completely equivalent to the second one – functions and lambda expressions are the same thing. And the last version is even slower according to fact 2.

Python map vs list comprehension

I like the first one better and there's an advantage to it. You can instead of

[ord(i) for i in 'some string']

write

(ord(i) for i in 'some string')

and have a generator instead of making a list. Great in some siutations.

Map vs list comprehension in Python

You might want to take a look at the responses to this question:

Python List Comprehension Vs. Map

Also, here's a relevant essay from Guido, creator and BDFL of Python:

http://www.artima.com/weblogs/viewpost.jsp?thread=98196

Personally, I prefer list comprehensions and generator expressions because their meaning is more obvious when reading the code.

List comprehension vs. lambda + filter

It is strange how much beauty varies for different people. I find the list comprehension much clearer than filter+lambda, but use whichever you find easier.

There are two things that may slow down your use of filter.

The first is the function call overhead: as soon as you use a Python function (whether created by def or lambda) it is likely that filter will be slower than the list comprehension. It almost certainly is not enough to matter, and you shouldn't think much about performance until you've timed your code and found it to be a bottleneck, but the difference will be there.

The other overhead that might apply is that the lambda is being forced to access a scoped variable (value). That is slower than accessing a local variable and in Python 2.x the list comprehension only accesses local variables. If you are using Python 3.x the list comprehension runs in a separate function so it will also be accessing value through a closure and this difference won't apply.

The other option to consider is to use a generator instead of a list comprehension:

def filterbyvalue(seq, value):
for el in seq:
if el.attribute==value: yield el

Then in your main code (which is where readability really matters) you've replaced both list comprehension and filter with a hopefully meaningful function name.

Is list comprehension implemented via map and lambda function?

No, list comprehensions are not implemented by map and lambda under the hood, not in CPython and not in Pypy3 either.

CPython (3.9.13 here) compiles the list comprehension into a special code object that outputs a list and calls it as a function:

~ $ echo 'x = [a + 1 for a in [1, 2, 3, 4]]' | python3 -m dis
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x107446f50, file "<stdin>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_CONST 2 ((1, 2, 3, 4))
8 GET_ITER
10 CALL_FUNCTION 1
12 STORE_NAME 0 (x)
14 LOAD_CONST 3 (None)
16 RETURN_VALUE

Disassembly of <code object <listcomp> at 0x107446f50, file "<stdin>", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 12 (to 18)
6 STORE_FAST 1 (a)
8 LOAD_FAST 1 (a)
10 LOAD_CONST 0 (1)
12 BINARY_ADD
14 LIST_APPEND 2
16 JUMP_ABSOLUTE 4
>> 18 RETURN_VALUE

Whereas the equivalent list(map(lambda: ...)) thing is just function calls:

~ $ echo 'x = list(map(lambda a: a + 1, [1, 2, 3, 4]))' | python3 -m dis
1 0 LOAD_NAME 0 (list)
2 LOAD_NAME 1 (map)
4 LOAD_CONST 0 (<code object <lambda> at 0x102701f50, file "<stdin>", line 1>)
6 LOAD_CONST 1 ('<lambda>')
8 MAKE_FUNCTION 0
10 BUILD_LIST 0
12 LOAD_CONST 2 ((1, 2, 3, 4))
14 LIST_EXTEND 1
16 CALL_FUNCTION 2
18 CALL_FUNCTION 1
20 STORE_NAME 2 (x)
22 LOAD_CONST 3 (None)
24 RETURN_VALUE

Disassembly of <code object <lambda> at 0x102701f50, file "<stdin>", line 1>:
1 0 LOAD_FAST 0 (a)
2 LOAD_CONST 1 (1)
4 BINARY_ADD
6 RETURN_VALUE

Performance of loops, list comprehensions and maps in Python 3

A few pointers:

  1. Wrap your code in functions for clarity.
  2. You are missing list creation and appends in code_for. This is the bulk of the cost of using an explicit for loop.
  3. You can then use timeit, or if you have Jupyter notebook, the magic %timeit command.

As below, map without lambda performs best, which makes sense since hex is a built-in. See Python List Comprehension Vs. Map for more details.

def code_for(n):
res = []
for i in range(n):
res.append(hex(i))
return res

def code_map(n):
return list(map(hex, range(n)))

def code_map_lambda(n):
return list(map(lambda x: hex(x), range(n)))

def code_list_comprehension(n):
return [hex(x) for x in range(n)]

%timeit code_for(10000) # 3.19 ms per loop
%timeit code_map(10000) # 1.69 ms per loop
%timeit code_map_lambda(10000) # 3.06 ms per loop
%timeit code_list_comprehension(10000) # 2.27 ms per loop

How can I replace map() function with list comprehension or for loop?

You want to call float() function over every element of lines[1].split(", ")[1:]

k1 = [float(x) for x in lines[1].split(", ")[1:]]


Related Topics



Leave a reply



Submit