This question already has an answer here:
I create a list of lists and want to append items to the individual lists, but when I try to append to one of the lists (a[0].append(2)
), the item gets 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]]
Whereas I would expect: [[1, 2], [1, 3]]
Changing the way I construct the initial list of lists, making b
a float instead of a list and putting the brackets inside .append()
, gives me the desired output:
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 intuitive that the result should be different. I know this has to do with there being multiple references to the same list, but I don't see where that is happening.
It is because the list contains references to objects. Your list doesn't contain
[[1 2 3] [1 2 3]]
, it is[<reference to b> <reference to b>]
.When you change the object (by appending something to
b
), you are changing the object itself, not the list that contains the object.To get the effect you desire, your list
a
must contain copies ofb
rather than references tob
. To copy a list you can use the range[:]
. For example, :The key is this part:
You are appending the same list twice, so both
a[0]
anda[1]
are references to the same list.In your second example, you are creating new lists each time you call append like
a.append([b])
, so they are separate objects that are initialized with the same float value.In order to make a shallow copy of a list, the idiom is
which when doubled will cause a to have two novel copies of the list
b
which will not give you the aliasing bug you report.