🎓 A1Learner
🔍

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?