Can anybody please explain to me the difference between these two ways of creating a list. Are they the same thing ? If not which one should I use ?
squares1 = [x**2 for x in range(1, 11)]
squares2 = list(x**2 for x in range(1, 11))
List comprehension offers a shorter syntax when you want to create a new list based on the values of an existing list. Based on a list of fruits, you want a new list, containing only the fruits with the letter "a" in the name. Without list comprehension you will have to write a for statement with a conditional test inside:
I just wanted to add a workaround way to avoid multiple function calls in python list comprehension: put the function call in a nested comprehension that only evaluates once. With your example, I mean this: [1+ f_ for f_ in [f ()] for x in xrange (5)] -- note that f () is only called once here. The function f will be called for every element.
Every list comprehension in Python includes three elements: expression is the member itself, a call to a method, or any other valid expression that returns a value. In the example above, the expression i * i is the square of the member value. member is the object or value in the list or iterable.
Nested List Comprehensions are nothing but a list comprehension within another list comprehension which is quite similar to nested for loops. Now by using nested list comprehensions same output can be generated in fewer lines of code. Lambda Expressions are nothing but shorthand representation of Python functions.
There is a slight bit of difference in their performance as can be seen from the following:
squares1 = [x**2 for x in range(1, 11)]
3.07 µs ± 70 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
squares2 = list(x**2 for x in range(1, 11))
3.65 µs ± 35.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
this can primarily be because in case 1 you are iterating and generating values for the list at the same time.
In case 2 you are generating values while iterating and then at the end of it converting the same to a list and this is then stored as a given variable.
I way I see it, first program directly initializes squares1 as a list through list comprehension.
The other one first creates a generator class object and then converts it into a list. I think first approach is more efficient.
There are little differences between lists and generators but as per my knowledge and experience lists do the job faster and generators do it lazily yielding single result for every iteration. For most of your tasks, I'd recommend opting for lists.
The first method is quicker. This is because when they get compiled into bytecode, the first one becomes
0 LOAD_CONST 0 (<code object <listcomp> at 0x7fc95aea9ed0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (range)
8 LOAD_CONST 2 (1)
10 LOAD_CONST 3 (11)
12 CALL_FUNCTION 2
14 GET_ITER
16 CALL_FUNCTION 1
18 RETURN_VALUE
and the second becomes
0 LOAD_NAME 0 (list)
2 LOAD_CONST 0 (<code object <genexpr> at 0x7fc95aea9ed0, file "<dis>", line 1>)
4 LOAD_CONST 1 ('<genexpr>')
6 MAKE_FUNCTION 0
8 LOAD_NAME 1 (range)
10 LOAD_CONST 2 (1)
12 LOAD_CONST 3 (11)
14 CALL_FUNCTION 2
16 GET_ITER
18 CALL_FUNCTION 1
20 CALL_FUNCTION 1
22 RETURN_VALUE
This means the second method takes two more instructions, slowing it down, even if it is just a tiny bit.
On my laptop, a million iterations of the first take 4.651s, and a million iterations of the second method takes 5.483s.
In first case you use list comprehension syntax. It's the fastest way to map some function on list in python.
In second case you create a generator
(x**2 for x in range(1000))
and send it to the list() function immediately. There is almost no difference in your case, because you get the same list and almost the same execution time:
%%timeit
[i**2 for i in range(1000)]
Out:
170 µs ± 774 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
list(i**2 for i in range(1000))
Out:
187 µs ± 2.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
But I'm not sure about memory usage in both cases - looks like they are the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With