简体   繁体   中英

Python : how to append new elements in a list of list?

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).

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.

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)]

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], []]

There is really something I do not get here !

a = [[]]*3 the problem here is that you are setting the lists to be the same reference, since arrays as well as dictionaries are stored as references.

>>> a = [[]]*3
>>> a[0] is a[1] or a[0] is a[2]
True
>>> a[0] is a[1] or a[0] is a[2] or a[1] is a[2]
True
>>> 

the same thing occurs if you do a = [{}]*3`

as such you must be careful, you can do either a list comprehension [[] for _ in xrange(3)] or statically define all 3 of your arrays [[], [], []] .

>>> a = [[] for _ in xrange(3)]
>>> a[0] is a[1] or a[0] is a[2] or a[1] is a[2]
False
>>> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM