Home > Enterprise >  Why Updating value from 2 lists behave differently? (one of the item in list is a single-item list)
Why Updating value from 2 lists behave differently? (one of the item in list is a single-item list)

Time:07-22

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. list of list

# 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.

  • Related