What is the difference between shallow copy and deep copy?
A shallow copy and a deep copy both produce a new container, but they differ in how they treat the objects referenced inside that container.
Shallow copy — creates a new outer object whose elements are the same references as the original. Mutating a nested object through either copy is visible in both.
Deep copy — recursively copies every nested object so the new structure shares nothing with the original. Mutating through one copy cannot affect the other.
How to make each:
import copy
a = [[1, 2], [3, 4]]
b = a.copy() # shallow (list.copy, slicing [:], list(a))
c = copy.copy(a) # shallow
d = copy.deepcopy(a) # deepThe difference in practice:
a = [[1, 2], [3, 4]]
b = copy.copy(a)
d = copy.deepcopy(a)
a[0].append(99)
b[0] # [1, 2, 99] — same inner list, same mutation
d[0] # [1, 2] — independent copyimport copy
# Assignment (NO copy - same object)
original = [[1, 2], [3, 4]]
assigned = original
assigned[0][0] = 99
print(original) # [[99, 2], [3, 4]] — affected!
# Shallow copy (new outer, shared inner)
original = [[1, 2], [3, 4]]
shallow = copy.copy(original) # or original[:] or list(original)
shallow[0][0] = 99
print(original) # [[99, 2], [3, 4]] — inner list affected!
shallow.append([5, 6])
print(original) # [[99, 2], [3, 4]] — outer not affected
# Deep copy (completely independent)
original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)
deep[0][0] = 99
print(original) # [[1, 2], [3, 4]] — unaffected!Assignment: both variables point to the same list — any modification is visible through both. Shallow copy: the outer list is new (append does not affect original), but inner lists are shared (modifying inner list [0][0] affects original).
Deep copy: everything is independent — no mutation propagates.
Show all three: assignment (same object), shallow copy (new outer, shared inner), deep copy (fully independent). The nested list mutation is the classic demonstration.
Know the shorthand methods: list[:], list.copy(), dict.copy() for shallow copies.