(I wasted too much time in examples and @Konrad Rudolph beat me to the answer, I'm basically saying the same thing as him)
Python is doing the equivalent of C pointer assignment under the hood, L1 held the address for a list in memory, and L2 just copied the same address.
You can check in code, simply using the is
operator.
>>> L1 is L2 True
When using slices though, a new list must be created, since it will differ from the original one, but python, being the sneaky bastard that it is, instead of copying everything, it just copies the references to the objects inside.
Here's a more elaborate example:
>>> L1 = [1, [2, 3], 4] >>> L2 = L1 >>> L2 [1, [2, 3], 4] >>> L1[1] is L2[1] True
Ok, so L1
holds a list with a list inside, you could replace this with a dictionary, string or any other python object. Notice that the is
operator returned True
for the list inside the list.
Then, if you do the slicing trick:
>>> L3 = L1[:2] >>> L3 [1, [2, 3]] >>> L3 is L1 False >>> L3[1] is L2[1] True
The outside list has changed, but the objects within remain the same, this is known as shallow copying. In fact, the same rules keep applying, to the point if that we add a new item to the list within the list:
>>> L3[1].append(9) >>> L3 [1, [2, 3, 9]] >>> L1 [1, [2, 3, 9], 4]
(notice the added 9) The list inside of both L1
and L3
are changed.
By contrast, you can do deepcopy
when shallow copying is not desired:
>>> from copy import deepcopy >>> L3 = deepcopy(L1) >>> L3 [1, [2, 3, 9], 4] >>> L3 is L1 False
slice
from a list creates a shallow copy...L2
. You're thinking of the shallow copy as deep because the thing you're thinking of as a shallow copy - direct assignment - is not actually a copy at all. This is a fundamental difference between languages like C++, where variables are places to put things and assignment creates copies, and languages like Python, where variables are names for things, and assignment just moves nametags around.