Warning! In Python, when it's a list and doing x = y
, changing values in y
changes x
.
It's not a copy by value but copy by reference here. E.g.
>>> x = [[1,2], [3,4]]
>>> y = x
>>> y[0][1] = 5
>>> x
[[1, 5], [3, 4]]
But how you're copying using x = y[:]
is right. And the chaining of [:]
is redundant.
First lets understand how to really "copy by value" for this nested list. To do so, in general, you can use the copy
module.
>>> import copy
>>> x = [[1,2], [3,4]]
>>> y = copy.deepcopy(x)
>>> y[0][1] = 5
>>> x
[[1, 2], [3, 4]]
>>> y
[[1, 5], [3, 4]]
From https://docs.python.org/3/faq/programming.html#how-do-i-copy-an-object-in-python , doing y = x[:]
is the same as using copy.copy
Now going back to the [:]
notation. If we go down the nested-ness and look at the types:
>>> x = [[1,2], [3,4]]
>>> type(x)
<class 'list'>
>>> type(x[0])
<class 'list'>
>>> type(x[:])
<class 'list'>
>>> type(x[:][0])
<class 'list'>
>>> type(x[:][0][0])
<class 'int'>
>>> type(x[:][0][0][0])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable
We see that if we directly assess the values inside the inner list at some point the integer value is not a list and so we can't get an index from it.
What happens when we keep on doing x[:][:][:][:][:]
, we see that it checks out at it's allowing us to keep on accessing the list but are we really getting into the nested list values when we do [:]
?
>>> type(x[:][:][:])
<class 'list'>
>>> type(x[:][:][:][:][:])
<class 'list'>
>>> type(x[:][:][:][:][:][:])
<class 'list'>
Here we see the types are not changing, and if we look at the actual value, if we start copying it:
>>> x = [[1,2], [3,4]]
>>> y = copy.deepcopy(x)
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:][:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:][:][:])
>>> y
[[1, 2], [3, 4]]
Essentially, you are accessing the full list at the first x[:]
and then the continuous chaining of [:]
isn't exactly accessing/traversing the nested loop, but just re-copying the copied list.
Think of z=x[:][:]
as:
y = x[:]
z = y[:]
It's a good point now to read the documentations/questions on slicing
To dig deeper, you'll have to go into the implementation.
https://github.com/python/cpython/blob/master/Objects/sliceobject.c