Does python copy
act the same as doing L[:]
or does L[:]
act more like deepcopy
or something else? Just a basic example would be:
from copy import copy
L = [1,2,3]
L[:]
# [1,2,3]
copy(L)
# [1,2,3]
Does python copy
act the same as doing L[:]
or does L[:]
act more like deepcopy
or something else? Just a basic example would be:
from copy import copy
L = [1,2,3]
L[:]
# [1,2,3]
copy(L)
# [1,2,3]
L.copy()
and L[:]
work identically - both are shallow copies. At first only L[:]
existed; .copy()
was added later so that generic code needing a copy could spell it in a unform way (dict.copy()
, set.copy()
, ...).
>>> L = [[1, 2], [3, 4]]
>>> L1 = L[:]
>>> [a is b for a, b in zip(L, L1)]
[True, True]
>>> L1 = L.copy()
>>> [a is b for a, b in zip(L, L1)]
[True, True]
>>> import copy
>>> L1 = copy.copy(L)
>>> [a is b for a, b in zip(L, L1)]
[True, True]
>>> L1 = copy.deepcopy(L) # this one differs!
>>> [a is b for a, b in zip(L, L1)]
[False, False]
Its complicated. Objects decide for themselves what slicing means. L[1:3]
is turned into a call to a magic method L.__getitem__(slice(1,3))
and the object decides what it should do with that. list
will make a shallow copy.
Other objects will do different things. A range object for example, gives you a new range object.
>>> range(5)[:3]
range(0, 3)
slicing in packages that do a lot of meta programming and get more complicated still.
To add onto Tim Peters' answer. From the copy
module documentation:
Shallow copies of dictionaries can be made using
dict.copy()
, and of lists by assigning a slice of the entire list, for example,copied_list = original_list[:]
.
Also, to address the comment below Tim Peters' answer, with regards to what is different between copy
and deepcopy
:
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
- A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
- A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
For instance look at the following:
>>> import copy
>>> l1 = [[1,2], 2, 3]
>>> l2 = copy.copy(l1)
>>> l1[0].append(3)
>>> l1
[[1, 2, 3], 2, 3]
>>> l2
[[1, 2, 3], 2, 3]
>>> l3 = copy.deepcopy(l1)
>>> l1[0].append(4)
>>> l1
[[1, 2, 3, 4], 2, 3]
>>> l3
[[1, 2, 3], 2, 3]
When l2
is copied with (shallow)copy
, the reference for the first entry is shared between l1
and l2
. So, mutating l1[0]
will also mutate l2[0]
. But in the deepcopy
(l3
), the copying is done recursively, so l1[0] != l3[0]
and mutating one does not influence the other.