-1

This list is initialized to be a list of 10 empty lists, and if I add to one sublist, as part of a loop, that changes all sublists:

x=[[]]*10
x[4]+=[4]
x
[[4], [4], [4], [4], [4], [4], [4], [4], [4], [4]]

If I use = then it works differently:

x=[[]]*10
x[4]=[4]
x
[[], [], [], [], [4], [], [], [], [], []]
x[4]+=[8]
x
[[], [], [], [], [4, 8], [], [], [], [], []]
x[2]+=[1]
x
[[1], [1], [1], [1], [4, 8], [1], [1], [1], [1], [1]]

It looks as if [[]]*10 creates 1 empty list and 10 references to the same empty list. Whereas ['']*10 actually creates 10 different '':

x=['']*10
x
['', '', '', '', '', '', '', '', '', '']
x[4]+='aa'
x
['', '', '', '', 'aa', '', '', '', '', '']

Using [[] for i in range(10)] works. However, I'd appreciate a good explanation for this.

Red
  • 26,798
  • 7
  • 36
  • 58
Cate
  • 1
  • "Whereas ['']*10 actually creates 10 different ''" no, it does the same thing, it creates 10 references to the same string object, it's just that string objects are immutable. – juanpa.arrivillaga Jul 24 '20 at 21:50

1 Answers1

0
>>> x=[[]]*10
>>> x[4]+=[4]
>>> x
[[4], [4], [4], [4], [4], [4], [4], [4], [4], [4]]

Yes, using nested lists in Python can lead to counter-intuitive results. Let's explain why this happens.

What Python translates this code to is essentially:

inner = []
x=[inner]*10
x[4]+=[4]  # same as inner+=[4]

I.e. all 10 elements of x are actually references to the same inner list. So if you change the 4th inner list, that change is reflected in each element of x (as they all are the same inner list).

One way around this is to define a nested list using a for-loop or list comprehension. This forces a new inner list to be constructed 10 separate times:

>>> x=[[] for _ in range(10)]
>>> x[4]+=[4]
>>> x
[[], [], [], [], [4], [], [], [], [], []]
xjcl
  • 12,848
  • 6
  • 67
  • 89