copy

Updated March 13, 2026 · Modules
copy shallow deep clone stdlib

The copy module provides two functions for creating copies of Python objects: copy() for shallow copies and deepcopy() for deep copies. Understanding the difference between these two is essential when working with mutable objects like lists, dictionaries, and custom objects.

Shallow Copy with copy()

A shallow copy creates a new object but inserts references to the original elements. For immutable objects like strings and numbers, this doesn’t matter. But for nested mutable objects, both the original and the copy share the same inner objects.

import copy

# Original list with nested list
original = [[1, 2], [3, 4]]

# Shallow copy
shallow = copy.copy(original)

# Modify the nested list in the copy
shallow[0][0] = 99

print(original)
# [[99, 2], [3, 4]]

print(shallow)
# [[99, 2], [3, 4]]

The inner lists are shared between original and shallow.

Creating shallow copies

# Three ways to create a shallow copy
list_copy = copy.copy(original_list)
list_copy = original_list[:]  # slice notation
list_copy = list(original_list)  # constructor

Deep Copy with deepcopy()

A deep copy creates a completely independent copy of an object and all objects it contains recursively. Changes to the deep copy never affect the original.

import copy

original = [[1, 2], [3, 4]]

# Deep copy
deep = copy.deepcopy(original)

# Modify the deep copy
deep[0][0] = 99

print(original)
# [[1, 2], [3, 4]]

print(deep)
# [[99, 2], [3, 4]]

copy() vs deepcopy()

Featurecopy.copy()copy.deepcopy()
PerformanceFasterSlower
Nested objectsSharedIndependent
Circular referencesMay cause issuesHandled correctly
MemoryLessMore

Parameters

copy(object)

ParameterTypeDescription
objectanyThe object to copy (must be copyable)

deepcopy(object, memo=None)

ParameterTypeDescription
objectanyThe object to copy recursively
memodictOptional dictionary for handling circular references

Common Patterns

Copying a dictionary

import copy

original = {"name": "Alice", "scores": [90, 85, 92]}

# Shallow copy — nested list is shared
shallow = copy.copy(original)
shallow["scores"].append(100)
print(original["scores"])  # [90, 85, 92, 100]

# Deep copy — completely independent
deep = copy.deepcopy(original)
deep["scores"].append(88)
print(original["scores"])  # [90, 85, 92, 100]

Copying a custom object

import copy

class Person:
    def __init__(self, name, hobbies):
        self.name = name
        self.hobbies = hobbies  # mutable list
    
    def __repr__(self):
        return f"Person({self.name}, {self.hobbies})"

original = Person("Alice", ["reading", "cycling"])

# Shallow copy — hobbies list is shared
shallow = copy.copy(original)
shallow.hobbies.append("hiking")
print(original.hobbies)  # ['reading', 'cycling', 'hiking']

# Deep copy — hobbies are independent
deep = copy.deepcopy(original)
deep.hobbies.append("swimming")
print(original.hobbies)  # ['reading', 'cycling', 'hiking']

Handling circular references

import copy

class Node:
    def __init__(self, name):
        self.name = name
        self.children = []
    
    def add_child(self, node):
        self.children.append(node)

# Create circular reference
root = Node("root")
child = Node("child")
root.add_child(child)
child.add_child(root)  # circular!

# deepcopy handles this correctly
new_root = copy.deepcopy(root)
print(new_root.children[0].children[0] is new_root)  # True

When to Use Each

Use copy() when:

  • The object contains only immutable types
  • You need better performance
  • You intentionally want nested objects shared

Use deepcopy() when:

  • The object contains mutable nested objects
  • You need complete independence from the original
  • You’re working with complex data structures like graphs or trees

See Also