Let's say I have an integer I want to make a list.
This works
[1]
However, this results in 'int' object is not iterable
list(1)
What is the difference between []
and list()
and when is it appropriate to use each?
Let's say I have an integer I want to make a list.
This works
[1]
However, this results in 'int' object is not iterable
list(1)
What is the difference between []
and list()
and when is it appropriate to use each?
They're entirely different things; list
is a built-in and []
are operators that can be used for, for example, either list comprehension or for list initialisation (which is what you're doing), but also for accessing certain indices in containers, etc. So you're kind of comparing apples and oranges.
Between list
with generator expressions and list comprehension, the latter is actually faster:
$ python3 -m timeit '[_ for _ in range(1000)]'
10000 loops, best of 5: 29.4 usec per loop
$ python3 -m timeit 'list(_ for _ in range(1000))'
5000 loops, best of 5: 42.9 usec per loop
If we disassemble into bytecode we get:
>>> dis.dis('[_ for _ in range(10)]')
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x10d0647c0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (range)
8 LOAD_CONST 2 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x10d0647c0, file "<dis>", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (_)
8 LOAD_FAST 1 (_)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE
list
plus a generator expression>>> dis.dis('list(_ for _ in range(10))')
1 0 LOAD_NAME 0 (list)
2 LOAD_CONST 0 (<code object <genexpr> at 0x10d0647c0, file "<dis>", line 1>)
4 LOAD_CONST 1 ('<genexpr>')
6 MAKE_FUNCTION 0
8 LOAD_NAME 1 (range)
10 LOAD_CONST 2 (10)
12 CALL_FUNCTION 1
14 GET_ITER
16 CALL_FUNCTION 1
18 CALL_FUNCTION 1
20 RETURN_VALUE
Disassembly of <code object <genexpr> at 0x10d0647c0, file "<dis>", line 1>:
1 0 LOAD_FAST 0 (.0)
>> 2 FOR_ITER 10 (to 14)
4 STORE_FAST 1 (_)
6 LOAD_FAST 1 (_)
8 YIELD_VALUE
10 POP_TOP
12 JUMP_ABSOLUTE 2
>> 14 LOAD_CONST 0 (None)
16 RETURN_VALUE
So outside of having to look up the name (list
, LOAD_NAME
), it seems to be mostly down to internal design; that the generator expression is popping indicates a stack.
Compare this with what you were doing:
>>> dis.dis('[1]')
1 0 LOAD_CONST 0 (1)
2 BUILD_LIST 1
4 RETURN_VALUE
>>> dis.dis('list(1)')
1 0 LOAD_NAME 0 (list)
2 LOAD_CONST 0 (1)
4 CALL_FUNCTION 1
6 RETURN_VALUE
First one builds a list, while the second is (after looking up the name) trying to call the function list
(which actually is a mutable sequence type class).
list()
takes an Iterable
(for instance: instances of set
, dict
, tuple
) as argument, []
takes an explicit listing of the elements or a comprehension.