Skip to main content

Shallow vs deep copies

Copying a container does not always copy the objects inside it. In Python, shallow copies duplicate the outer container but keep references to the same nested values.

What is happening?

This looks like a safe copy:

original = {"items": [1, 2, 3]}
copied = original.copy()

copied["items"].append(4)

print(original)
print(copied)

Output:

{'items': [1, 2, 3, 4]}
{'items': [1, 2, 3, 4]}

What you might expect: Changing copied leaves original alone.

What actually happens: Both dictionaries point to the same nested list.

Why this matters

This bug shows up when code copies:

  • nested lists or dictionaries
  • default configuration objects
  • parsed JSON-like data
  • test fixtures that are modified between cases

The outer object is new, but the inner mutable values are shared.

Use deepcopy() when you truly need independence

from copy import deepcopy

original = {"items": [1, 2, 3]}
copied = deepcopy(original)

copied["items"].append(4)

print(original)
print(copied)

Output:

{'items': [1, 2, 3]}
{'items': [1, 2, 3, 4]}

deepcopy() recursively copies nested objects, so later mutation does not leak back into the original structure.

Do not use deepcopy() blindly

deepcopy() is useful, but it is not always the best answer:

  • it can be slower than a targeted copy
  • it may copy more than you intended
  • it can hide a design that mutates shared state too freely

Sometimes the better fix is to build a fresh structure explicitly.

Rules of thumb

  • A shallow copy only copies the outer container.
  • Be careful with nested mutable objects.
  • Use deepcopy() when you need a truly independent nested copy.
  • Prefer explicit fresh structures when the copied shape is small and important.