2

I was looking online and I came across these 3 segments of code. The question is to predict the output and explain why.

Example 1:

x = 42
y = x
x = x + 1
print x
print y

Output Example 1:

43
42

Example 2:

x = [1, 2, 3]
y = x
x[0] = 4
print x
print y

Output Example 2:

[4, 2, 3]
[4, 2, 3]

Example 3:

x = ['foo', [1,2,3], 10.4]
y = list(x) # or x[:]
y[0] = 'fooooooo'
y[1][0] = 4
print x
print y

Output Example 3:

['foo', [4, 2, 3], 10.4]
['fooooooo', [4, 2, 3], 10.4]

For the most part I understand that this is a question about shallow and deep copying but I can't seem to wrap my head around this simple thing. In Example 2 at x[0] = 4 I understand that x and y are pointing to the same object and therefore both x and y are redefined and not just x in this statement. But then why in Example 3 does this same logic not follow. At y[0] = 'fooooooo' this should cause x and y to be redefined, just like the following line at y[1][0] = 4 causes both x and y to be redefined together.

Ely Fialkoff
  • 642
  • 1
  • 5
  • 12

1 Answers1

1

Ok so we can dissect this a bit more:

>>> x = ['foo', [1,2,3], 10.4]
>>> y = list(x) # or x[:]
>>> z=x
>>> id(x)
4354889544
>>> id(y)
4354890184
>>> id(z)
4354889544

>>> y[0] = 'fooooooo'
>>> y[1][0] = 4
>>> y
['fooooooo', [4, 2, 3], 10.4]
>>> x
['foo', [4, 2, 3], 10.4]
>>> id(x[1])
4354889672
>>> id(y[1])
4354889672

See it now? When you use the function List() it is creating a new object in a new memory location... but to save space python will keep the same pointer to the mutable internal objects, like the list. This article can explain more what is mutable and what is not.

bison
  • 739
  • 5
  • 21
  • If `y` is a new object `list()` then why would `y[1][0]` point back to a shared list and not `y`'s own value? – Ely Fialkoff Aug 17 '18 at 13:06
  • Python tries to limit the new memory space so the new list just still holds a shared pointer with the original list for that mutable object.`y[1] -> mem <- x[1]` – bison Aug 17 '18 at 13:12