Here is a very simple program:
a = [[]]*3
print str(a)
a[0].append(1)
a[1].append(2)
a[2].append(3)
print str(a[0])
print str(a[1])
print str(a[2])
Here is the output I was expecting:
[[], [], []]
[1]
[2]
[3]
But instead I get this :
[[], [], []]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
There is really something I do not get here !
You must do
a = [[] for i in xrange(3)]
not
a = [[]]*3
Now it works:
$ cat /tmp/3.py
a = [[] for i in xrange(3)]
print str(a)
a[0].append(1)
a[1].append(2)
a[2].append(3)
print str(a[0])
print str(a[1])
print str(a[2])
$ python /tmp/3.py
[[], [], []]
[1]
[2]
[3]
When you do something like a = [[]]*3
you get the same list []
three times in a list. The same means that when you change one of them you change all of them (because there is only one list that is referenced three times).
You need to create three independent lists to circumvent this problem. And you do that with a list comprehension. You construct here a list that consists of independent empty lists []
. New empty list will be created for each iteration over xrange(3)
(the difference between range
and xrange
is not so important in this case; but xrange
is a little bit better because it does not produce the full list of numbers and just returns an iterator object instead).
The fundamental problem with your approach is that when you multiply the list by three, the resultant list contains three of the same list. So a[0]
, a[1]
, and a[2]
all reference the same thing. When you append to any of these, you append to the same list. This is why the effect of your append()
calls seem to be triplicated.
Instead, generate your list-of-lists without referencing the same list. As an example, you can use list comprehension, like so.
[[] for i in range(3)]
When you write:
a = [[]]*3
You won't make 3 copies of the inner empty list, but instead you make 3 references to the same object.
The same way, if you do:
b = [1,2,3]
c = b
c.append(4)
print b
You get as the output:
[1, 2, 3, 4]
That is because b and c are two different references (you may say two different names) to the same list. You may change the object from any reference, but you will see the results from all of them, since they point to the same thing.
this will give you a clear idea, in l all object have the same id() and all are mutable so editing any one of them will automatically edit other too, as they all are just refernces to a same object with id=18671936 and in m all have different id(), so all of them are different objects.
>>> l = [[]]*4
>>> for x in l:
print(id(x))
18671936
18671936
18671936
18671936
>>> m=[[],[],[],[]]
>>> for x in m:
print(id(x))
10022256
18671256
18672496
18631696
So,you should create your list like this:
>>> a=[[] for _ in range(4)]
>>> a[0].append(1)
>>> a[2].append(5)
>>> a
[[1], [], [5], []]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With