2

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]
David542
  • 104,438
  • 178
  • 489
  • 842
  • 1
    That's not a very useful example, because integers are immutable - you wouldn't be able to tell the difference between a deep and shallow copy anyway. – jonrsharpe Jun 23 '21 at 22:27

3 Answers3

5

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(), ...).

Examples

>>> 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]
Tim Peters
  • 67,464
  • 13
  • 126
  • 132
1

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.

tdelaney
  • 73,364
  • 6
  • 83
  • 116
1

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.

Dair
  • 15,910
  • 9
  • 62
  • 107