The problem

When you copy a list containing other lists, a simple assignment doesn't create a true copy—both variables point to the same object. This can cause unexpected changes.

Shallow copy

A shallow copy creates a new object, but nested objects are still shared:

import copy

original = [[1, 2, 3], [4, 5, 6]]
shallow = copy.copy(original)

# Modify nested list:
shallow[0][0] = 99

print(original)  # [[99, 2, 3], [4, 5, 6]] — changed!
print(shallow)   # [[99, 2, 3], [4, 5, 6]]

Deep copy

A deep copy creates completely independent copies of all nested objects:

import copy

original = [[1, 2, 3], [4, 5, 6]]
deep = copy.deepcopy(original)

# Modify nested list:
deep[0][0] = 99

print(original)  # [[1, 2, 3], [4, 5, 6]] — unchanged!
print(deep)      # [[99, 2, 3], [4, 5, 6]]

When to use each

  • Shallow copy: When nested objects are immutable (like strings, numbers) or you want to share nested data
  • Deep copy: When you need completely independent copies of nested mutable objects

For simple lists

# For flat lists, these work the same:
list1 = [1, 2, 3]
list2 = list1.copy()  # or list(list1) or list1[:]
list2[0] = 99
print(list1)  # [1, 2, 3] — unchanged