A shallow copy creates a new outer object, but nested objects are still shared references. A deep copy recursively copies nested objects so the new structure does not share mutable children (with caveats for recursive/special objects).
import copy original = [[1, 2], [3, 4]] shallow = copy.copy(original) # or original.copy(), list(original), original[:] deep = copy.deepcopy(original) shallow[0].append(99) print(original) # [[1, 2, 99], [3, 4]] ← nested list shared print(shallow) # [[1, 2, 99], [3, 4]] print(deep) # [[1, 2], [3, 4]] ← independent deep[1].append(100) print(original) # unchanged nested second row
When it matters
- Nested lists/dicts/configs: shallow copies cause surprising cross-talk.
- Flat lists of immutables (ints, strings): shallow is usually enough.
- Assignment (
b = a) is not a copy; both names refer to the same object.
Interview tip: Draw one outer box vs shared inner boxes for shallow; fully separate trees for deep.