Question:
Using Python 2.7.12
I need to create a list like this:
lista = [[],[],[],[],.........,[]]
This list needs to have a very large number of lists within it (hence the ……..). I found the following way to do this out there:
lista = [[]]*n
Where "n" is the number of sub-lists. But with that I come to a problem. Below is an example (with a much smaller number of sub-lists for illustration).
lista = [[]]*3
lista[0].append(1)
lista[1].append(2)
print lista
The output should be:
[[1], [2], []]
But the output of this code is:
[[1, 2], [1, 2], [1, 2]]
I have no idea what it is, nor do I know/found another way to create such a list.
Answer:
The problem with the code you tried to do:
lista = [[]]*n
The object that will be repeated, []
, is initialized only once, when its reference is defined and this is used in the other positions. To demonstrate this, just scroll through the list and display the id
value:
lista = [[]]*3
for l in lista:
print id(l)
See working on Repl.it | Ideone | GitHub GIST
The three values will be the same as in:
47056207983464
47056207983464
47056207983464
To better demonstrate what happens, just check the opcode executed, with the help of the dis
module:
>>> print dis.dis('[[]]*3')
1 0 BUILD_LIST 0
2 BUILD_LIST 1
4 LOAD_CONST 0 (3)
6 BINARY_MULTIPLY
8 RETURN_VALUE
Note that the BUILD_LIST
operation is executed twice, once for the internal list and once for the external one; then constant 3 is loaded and the values are multiplied. That is, only one reference to the internal list is created, which is multiplied by 3.
To work around this problem, you can use the list comprehension :
lista = [[] for _ in xrange(n)]
See working on Repl.it | Ideone | GitHub GIST
Thus, n
distinct references are defined.
For the same solution in Python 3, just replace the
xrange
function withrange
.
This even happens with all mutable types in Python. For example, if you have a class Foo
and want to create a list of instances, you can't do:
lista = [Foo()]*3
Making it even clearer that Foo
will only be instantiated once and the created object will be multiplied by 3.