-2

I need your help. I am confused about the output of the following code.


a = []
b = []

for j in range(2):
    b.append(j)
a.append(b)
print(b)
print(a)

for i in range(2):
    b.append(i)
print(b)
print(a)

a.append(b)
print(a)

I thought that the 3rd "print(a)" should give [[0,1],[0, 1, 0, 1], but it actually gives [[0, 1, 0, 1], [0, 1, 0, 1]]. It seems that after the 2nd loop the "a" is automatically updated, sth that is not happening in the following case, for example, where both prints should give 0:


x=0
y=x
print(y)  
x=9
print(y)

Does anyone know what changes from the 1st "print(a)" to the 2nd and why they give different outputs?

Thanks!

The code along with the outputs

  • a contains two references to b. By the end of the program, b contains [0, 1, 0, 1]. So because a contains two references to b, it has two of [0, 1, 0, 1]. If you add the values as integers, rather than as a reference, you will get your expected output – Sri Apr 16 '20 at 21:34
  • @Sri "add as integers instead of reference" makes no sense. All objects in Python are references. To observe the expected behavior, the OP ought to _copy_ the list before appending it to the other list. – ApproachingDarknessFish Apr 16 '20 at 21:37

2 Answers2

0

Yes, under the hood, python actually uses pointers. So when you add b to a, it actually adds the pointer, not the values of the list.

kind of like this...

If you have the address of a plot of land, and put that on a list, If you go back to it, it's a plot of land. And then put the address of the plot of land on the same list, when you build a house on it. If you go back to it, it will have a house on it. But if you go back to the first address on the list (the same address), it won't be a plot of land, even though it was like that when you left it, it will still have the house on it.

what you want to do is:

a = []
b = []

for j in range(2):
    b.append(j)
a.append(list(tuple(b)))
print(b)
print(a)

for i in range(2):
    b.append(i)
print(b)
print(a)

a.append(b)
print(a)

if you cast b as a tuple the first time, and then back to a list, it will create a new object, and a different pointer, and thus a different house with a different address, so it still will be that original plot of land when you get there.

mark pedersen
  • 245
  • 1
  • 9
0

When you do a.append(b), you're appending a reference to b, not a new copy of it -- so whenever you append to b, you'll see that reflected in a as well.

Since you append b to a three times, by the end of your script a == [b, b, b].

To build b, you append the values 0, 1, 0, 1 to it.

Hence by the end of your script:

b == [0, 1, 0, 1]
a == [b, b, b] == [[0, 1, 0, 1], [0, 1, 0, 1], [0, 1, 0, 1]]

What's more, if you modify any of the elements of a, you'll see that they all change together (because they're all the same b).

>>> a[0][3] = 2
>>> print(a)
[[0, 1, 0, 2], [0, 1, 0, 2], [0, 1, 0, 2]]
>>> print(b)
[0, 1, 0, 2]
Samwise
  • 68,105
  • 3
  • 30
  • 44