Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python list function or list comprehension

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))
like image 334
Oppac Avatar asked Aug 15 '18 15:08

Oppac


People also ask

What is list comprehension in Python?

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:

How to avoid multiple function calls in Python list comprehension?

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.

How do you understand a list in Python?

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.

What is the difference between list comprehension and lambda expression in Python?

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.


4 Answers

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.

like image 198
Inder Avatar answered Oct 13 '22 15:10

Inder


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.

like image 3
Amit Prafulla Avatar answered Oct 13 '22 14:10

Amit Prafulla


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.

like image 2
dangee1705 Avatar answered Oct 13 '22 15:10

dangee1705


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.

like image 1
Mikhail Stepanov Avatar answered Oct 13 '22 14:10

Mikhail Stepanov