ProgrammingData Engineer

Explain the difference between shallow copy and deep copy, as well as the behavior of copy.copy and copy.deepcopy when copying complex objects. Provide an example where misunderstanding led to a bug.

Pass interviews with Hintsage AI assistant

Answer.

Shallow copy creates a new top-level object, but nested objects (list elements, nested dictionaries, etc.) share memory with the original. Deep copy recursively copies all levels of objects.

It can be used through the copy module:

import copy original = [[1, 2], [3, 4]] shallow = copy.copy(original) deep = copy.deepcopy(original) shallow[0][0] = 99 # Changes both original and shallow print(original) # [[99, 2], [3, 4]] # Now with deep original = [[1, 2], [3, 4]] deep = copy.deepcopy(original) deep[0][0] = 99 print(original) # [[1, 2], [3, 4]]

Features:

  • copy.copy(obj): copies only the "wrapper"
  • copy.deepcopy(obj): fully recursive copying
  • Some objects (such as open files, sockets) are not copied by deep copy (exception)

Trick question.

What happens when copying a tuple that contains mutable objects?

Answer with example:

tuple is immutable, but its elements can be mutable (e.g., a list). Shallow copy and deep copy differ:

import copy t = ([1, 2], [3, 4]) shallow = copy.copy(t) deep = copy.deepcopy(t) shallow[0][0] = 99 print(t) # ([99, 2], [3, 4]) # With deep copy: t = ([1, 2], [3, 4]) deep = copy.deepcopy(t) deep[0][0] = 88 print(t) # ([1, 2], [3, 4])

Examples of real errors due to misunderstanding the topic nuances


Story

In a document processing application, data was stored in a list inside a dictionary. When copying objects using copy.copy, nested elements were unintentionally changed when modifying the new object. As a result, the original data was changed in other parts of the system! Data corruption occurred. It was fixed only by replacing it with deepcopy.


Story

In a machine learning project, when saving model hyperparameters, a list of configurations was copied using standard assignment and shallow copy, causing different experiments to mutually change their parameters. The source of the bug was found after diagnosing the behavior of copying nested lists via deepcopy.


Story

In financial software, deep copy was accidentally applied to an object that included an open file (handle), which resulted in TypeError: cannot pickle '_io.TextIOWrapper' object — because copy.deepcopy under the hood uses pickle. It was fixed through explicit handling of such fields or calling shallow copy.