Python list function or list comprehension
Question:
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))
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.
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.
Both are identicle.. to know more abouts list watch this video this video may help you
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))
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.
Both are identicle.. to know more abouts list watch this video this video may help you