Why does foo.append (bar) affect all items in a list of lists?

I am creating a list of lists and I want to add items to separate lists, but when I try to add one of the lists ( a[0].append(2) ), the item is added to all lists.

 a = [] b = [1] a.append(b) a.append(b) a[0].append(2) a[1].append(3) print(a) 

Gives: [[1, 2, 3], [1, 2, 3]]

While I would expect: [[1, 2], [1, 3]]

Changing the way you create the original list of lists, making b float instead of a list and placing the brackets inside .append() , will give me the desired result:

 a = [] b = 1 a.append([b]) a.append([b]) a[0].append(2) a[1].append(3) print(a) 

Gives: [[1, 2], [1, 3]]

But why? It is not interesting that the result should be different. I know that this is due to the fact that there are several links to the same list , but I do not see where this is happening.

+7
source share
3 answers

This is because the list contains references to objects. Your list does not contain [[1 2 3] [1 2 3]] , it is [<reference to b> <reference to b>] .

When you change an object (adding something to b ), you change the object itself, not the list containing the object.

To get the desired effect, your list a should contain copies of b , and not references to b . To copy the list, you can use the range [:] . For example:

 >>> a=[] >>> b=[1] >>> a.append(b[:]) >>> a.append(b[:]) >>> a[0].append(2) >>> a[1].append(3) >>> print a [[1, 2], [1, 3]] 
+20
source

The key to this part:

 a.append(b) a.append(b) 

You add the same list twice, so both a[0] and a[1] are links to the same list.

In your second example, you create new lists every time you call append as a.append([b]) , so they are separate objects that are initialized with the same float value.

+1
source

To make a shallow copy of the list, idiom

 a.append(b[:]) 

which, when doubled, will result in two new copies of list b that will not inform you of the alias error.

+1
source

All Articles