0

If I execute the following code:

l = ["A", "B", "C"]
for i in range(len(l)):
    e = l.pop(0)
    l.append(e)
    print(l)

The output is as expected and iterates the list as expected placing the first element at the end:

['B', 'C', 'A']
['C', 'A', 'B']
['A', 'B', 'C']

HOWEVER, if I attempt to build a data structure to store the lists:

fl = []
l = ["A", "B", "C"]
for i in range(len(l)):
    e = l.pop(0)
    l.append(e)
    fl.append(l)
print(fl)

The output is not as expected:

[['A', 'B', 'C'], ['A', 'B', 'C'], ['A', 'B', 'C']]

Can anyone please explain this?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
RandallShanePhD
  • 5,406
  • 2
  • 20
  • 30
  • In this specific case, `fl.append(l[:])` will do the trick. But please see the link above for more detailed explanations – Tomerikoo Apr 20 '21 at 22:16
  • "a data structure to store the lists" — Not *lists*; it's just *one list* that you're altering each time. – khelwood Apr 20 '21 at 22:17
  • 1
    Might be a better-suited duplicate: [Why does foo.append(bar) affect all elements in a list of lists? (duplicate)](https://stackoverflow.com/q/6360286/6045800) – Tomerikoo Apr 20 '21 at 22:23

1 Answers1

1

You are appending a reference to the end of fl, not a copy of the l list. This means you have a list of three references all referring to the same l list.

It seems you want to copy l each time, which you can do with list(l) or l[:]

fl = []
l = ["A", "B", "C"]
for i in range(len(l)):
    e = l.pop(0)
    l.append(e)
    fl.append(l[:]) # modified to append a copy of l
print(fl)

outputs:

[['B', 'C', 'A'], ['C', 'A', 'B'], ['A', 'B', 'C']]

Another way to see that they all refer to the same list is to modify l after the loop and see the difference reflected in the output

fl = []
l = ["A", "B", "C"]
for i in range(len(l)):
    e = l.pop(0)
    l.append(e)
    fl.append(l)

print(fl)
print('appending')
l.append('D') 
print(fl)

outputs:

[['A', 'B', 'C'], ['A', 'B', 'C'], ['A', 'B', 'C']]
appending
[['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D']]
Ryan Haining
  • 35,360
  • 15
  • 114
  • 174