Why results of map() and list comprehension are different?
They are different, because the value of i
in both the generator expression and the list comp are evaluated lazily, i.e. when the anonymous functions are invoked in f
.
By that time, i
is bound to the last value if t
, which is -1.
So basically, this is what the list comprehension does (likewise for the genexp):
x = []
i = 1 # 1. from t
x.append(lambda: i)
i = -1 # 2. from t
x.append(lambda: i)
Now the lambdas carry around a closure that references i
, but i
is bound to -1 in both cases, because that is the last value it was assigned to.If you want to make sure that the lambda receives the current value of i
, do
f(*[lambda u=i: u for i in t])
This way, you force the evaluation of i
at the time the closure is created.Edit: There is one difference between generator expressions and list comprehensions: the latter leak the loop variable into the surrounding scope.
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 list comprehension). 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
Python: List Comprehensions vs. map
All your timing results can be explained by theses facts:
CPython has a rather high function call overhead.
map(f, it)
is slightly faster than[f(x) for x in it]
.
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.
why not always use map if its faster than the rest (list comprehension, loop (various variants))?
Performance is not always the first priority when writing code. In a lot of case, we might not care about the µs lost in the list comprehension, if it helps reading and maintaining the code later.
I believe list comprehension are more easier to read and understand than map
, despite the small performance lost.
EDIT, as ayhan described in comments, your example is biased since map
returns a generator, so it does not generate anything until iterated over, while the list comprehension compute the whole list on declaration.
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.
Equivalent of List Comprehension Using Map and Filter
Since both filter
and map
work over individual items in a sequence, you would have to view your logic from the perspective of each item in the list, rather than a combination of items, and that means you need to rephrase the expressions used in your list comprehension as functions of individual items. Instead of the filter condition x + y == tgt
, therefore, it is beneficial to view it as x == tgt - y
, where y
also has to be an item in the num
list, so that your list comprehension can be rewritten as:
[num.index(x) for x in num if x in {tgt - y for y in num}]
With this equivalent list comprehension, it then becomes clear that to implement the filter condition would need to make a set by mapping each item in num
to its difference with tgt
, which can be done with the tgt.__sub__
method, and test each item x
in num
if it is a member of the set, which can be done with the set's __contains__
method, and finally, map the filtered sequence to num.index
to output the index of each matching item:list(map(num.index, filter(set(map(tgt.__sub__, num)).__contains__, num)))
This returns:[0, 1, 2, 4, 6, 7]
Performance of loops, list comprehensions and maps in Python 3
A few pointers:
- Wrap your code in functions for clarity.
- You are missing list creation and appends in
code_for
. This is the bulk of the cost of using an explicitfor
loop. - You can then use
timeit
, or if you have Jupyter notebook, the magic%timeit
command.
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
Related Topics
How to Define a Class Constant Inside an Enum
Selenium Webdriver in Python - Files Download Directory Change in Chrome Preferences
How to Resolve a Tesseractnotfounderror
Writing List of Strings to Excel CSV File in Python
How to Get Precision, Recall and F-Measure from Confusion Matrix in Python
How to Get a List of Keywords in Python
How to Multiply Individual Elements of a List with a Number
Python & Pandas: How to Query If a List-Type Column Contains Something
How to Set a Proxy for Phantomjs/Ghostdriver in Python Webdriver
Errors While Building/Installing C Module for Python 2.7
Django Unique Together (With Foreign Keys)
Get the String Within Brackets in Python
"Pip Install --Editable ./" VS "Python Setup.Py Develop"
Round Up to Second Decimal Place in Python