[] and list() and 'int' object is not iterable in Python
Solution 1:
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:
- for list comprehension
>>> 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
- for
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).