TKoL
TKoL

Reputation: 13892

Multi-Referenced Nested Lists

I was looking at this guy's post: https://stackoverflow.com/a/2573965/1959054

He was talking about testing people's Python proficiency by asking them the outputs of the following code:

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

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

I predicted those two outputs successfully, having just read about similar scenarios with mutable lists and immutable strings in a book. Then he gave this example:

x = ["foo",[1,2,3],10.4]
y = list(x)
y[0] = 'foooooo'
y[1][0] = 4
print x
print y

This left me very confused. You see, I predicted that x would print as ["foo",[1,2,3],10.4] and y would print as ["foooooo",[4,2,3],10.4].

x actually printed as ["foo",[4,2,3],10.4], meaning that, even though the outside list was referencing different list objects, the inner list at x[1] and y[1] was still referencing the same object.

I hadn't come across this before.

My primary question is, if you want to make y equivalent to x, but not reference the same list, and ALSO make sure any nested lists aren't referencing the same lists as well, how do you do that? y = list(x) seems to only handle the outer list.

My secondary question is just to get any help conceptually understanding why this works this way.

Upvotes: 2

Views: 55

Answers (1)

jonrsharpe
jonrsharpe

Reputation: 121975

Your first question is answered by copy.deepcopy(), which (docs):

constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

from copy import deepcopy
y = deepcopy(x)

As to why this happens, the standard list construction from list() (and the common slice copy x[:]) creates only a shallow copy, i.e. (docs again, emphasis mine):

constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

Upvotes: 1

Related Questions