Python Copying in Depth
A shallow copy is a new outer object that still shares the objects inside. A deep copy is a new object with new copies of everything inside.
A shallow copy of a flat list
This copy has its own outer list. Appending to it leaves the original alone.
import copy
a = [1, 2, 3]
b = copy.copy(a)
b.append(4)
print(a)
print(b)The inside is still shared
The inner lists were not copied. Changing one through b changes what a sees.
import copy
a = [[1, 2], [3, 4]]
b = copy.copy(a)
b[0].append(99)
print(a)New outside, same inside
is shows the truth clearly. The outer lists differ, but the first inner list is shared.
import copy
a = [[1, 2], [3, 4]]
b = copy.copy(a)
print(a is b)
print(a[0] is b[0])A deep copy copies the inside too
deepcopy() copies every level. Now the inner change stays inside b.
import copy
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
b[0].append(99)
print(a)
print(b)
print(a[0] is b[0])Some values need no copy
A string is immutable, so it cannot change in place. Building a longer string moves the label instead.
name = "Ada"
other = name
other = other + " Lovelace"
print(name)
print(other)Example
import copy
original = [["math", 90], ["art", 85]]
shallow = copy.copy(original)
shallow[0][1] = 0
print("After shallow change:", original)
original2 = [["math", 90], ["art", 85]]
deep = copy.deepcopy(original2)
deep[0][1] = 0
print("After deep change:", original2)
print("Deep copy:", deep)Key points
- Shallow copy: a new outer object that still shares the objects inside
- Deep copy: a new object with new copies of everything inside it
- Use copy.copy() to make a shallow copy
- Use copy.deepcopy() to make a deep copy
- Immutable values need no copy.
- They cannot change in place anyway.
- Copy at the depth you mutate.
- That is the safe rule of thumb.
In this example, original holds a list of lists. shallow is a shallow copy of it. Setting shallow[0][1] = 0 reaches the shared inner list. So original changes too, and its math score becomes 0. That is the nested-list trap. The second half starts fresh with original2. deep is a deep copy, so its inner lists are new objects. Setting deep[0][1] = 0 changes only the copy. original2 keeps its score of 90.
Note
A shallow copy protects the outer list only.
Nested lists stay shared, and that is where shallow copies bite.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
You copy a list of lists with copy.copy(). Then you change a value in a nested list of the copy. What happens to the original?