x = [1,3,6,[18]]
y = list(x)
print(y)
x[3][0] = 15
x[1] = 12
print(x)
print(y)
In the above code, updating x[3][0]
in x
is reflected in y
(which is the list of x
), but the update in x[1] = 12
is not reflected in y
Why this is not getting updated in y
?
CodePudding user response:
A picture worth thousand words. Here is the picture that is missing: (let's pretend forgetting all *terminology for a moment now)
Credits to all posts. Labor (of the wording & picturing) is mine.
First thing first, when you try to use list constructor to create y: list(x) or [:] it just produces a shallow copy (ie. the outermost container is duplicated, but the copy is filled with reference to the same item (as [18] shown in picture)
So later if you update x's [18] it will update the reference point - that's why both lists see the change of 15. But when you update other object, it directly change the integer object in the container x but not in y.
Lesson learned - Copies are shallow by Default! in Python.
# See different code example:
x = [1,3,6,[18]]
y = x[:] # new list, but it's shallow copy (last item)
print(x, id(x)) # different memory
print(y, id(y)) # but same content to start with
x[3][0] = 15 # assign new value - reflect in both x, y
x[1] = 12 # assign new value - only affect x
print(x, id(x))
print(y, id(y)) # last item got changed too; because sharing
https://i.imgur.com/3MJLTUE.png
CodePudding user response:
What is happening is a shallow copy. When you wrote y=list(x)
, this created a reference from y to x, and not an actual copy. What you need is a deep copy, a copy that creates a new list(including nested lists) instead of referencing the old one. .copy()
won't work, because nested lists are still references even though the rest of the copied list is a separate list.
Here is the code for a deep copy:
import copy
x=[1,3,6,[18]]
y=copy.deepcopy(x)
print(y)
x[3][0]=15
x[1]=12
print(x)
print(y)
CodePudding user response:
By using list()
you create a new reference (y) to the same addresses in memory that (x) is referring.
Element 1 in x and y is an integer which is immutable. Once you use x[1]=12
basically you create a new object in memory for number 12 and x[1] will refer to that object. However, y[1] still refers to previous object (i.e. 3).
Element 3 in in x and y is a list which is mutable. Once, you use x[3][0]
, it updates the same object in memory. So, both x and y reflect the change.
I hope I could convey the concept.