Fundamentals 8 min read

Mastering Shallow vs Deep Copy in Python: When and How to Use Them

This guide explains the difference between Python's shallow and deep copy mechanisms, shows the built‑in tools available, and provides ten concrete code examples covering lists, dictionaries, custom objects, tuples, sets and multi‑level nesting to help you choose the right copying strategy for reliable API test automation.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Mastering Shallow vs Deep Copy in Python: When and How to Use Them

Introduction

When writing API automation test scripts, copying data structures is often required to simulate different test scenarios. Python provides two copy mechanisms—shallow copy and deep copy—and understanding their differences is crucial for maintaining test data consistency and accuracy.

Shallow Copy vs Deep Copy

Shallow copy copies only the top‑level object’s reference; mutable elements inside the object are not duplicated. Deep copy copies the reference and recursively duplicates every nested object, producing an entirely independent structure.

Copy Tools

The copy module offers copy() for shallow copies and deepcopy() for deep copies. Built‑in methods such as list.copy() or dict.copy() also perform shallow copies.

Example Code

Example 1: Basic List Copy

import copy
original = [1, 2, 3]
shallow_copy = original[:]
deep_copy = copy.deepcopy(original)
original.append(4)
print("Original:", original)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)

Output:

Original: [1, 2, 3, 4]
Shallow copy: [1, 2, 3]
Deep copy: [1, 2, 3]

Example 2: Nested List

original = [[1, 2], [3, 4]]
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
original[0].append(5)
print("Original:", original)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)

Output:

Original: [[1, 2, 5], [3, 4]]
Shallow copy: [[1, 2, 5], [3, 4]]
Deep copy: [[1, 2], [3, 4]]

Example 3: List Slice Copy

original = [1, 2, 3, [4, 5]]
shallow_copy = original[:]
original[3].append(6)
print("Original:", original)
print("Shallow copy:", shallow_copy)

Output:

Original: [1, 2, 3, [4, 5, 6]]
Shallow copy: [1, 2, 3, [4, 5, 6]]

Example 4: Dictionary Copy

original = {'a': 1, 'b': 2}
shallow_copy = original.copy()
deep_copy = copy.deepcopy(original)
original['c'] = 3
print("Original:", original)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)

Output:

Original: {'a': 1, 'b': 2, 'c': 3}
Shallow copy: {'a': 1, 'b': 2}
Deep copy: {'a': 1, 'b': 2}

Example 5: Nested Dictionary

original = {'a': 1, 'b': {'c': 2}}
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
original['b']['c'] = 3
print("Original:", original)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)

Output:

Original: {'a': 1, 'b': {'c': 3}}
Shallow copy: {'a': 1, 'b': {'c': 3}}
Deep copy: {'a': 1, 'b': {'c': 2}}

Example 6: Custom Object Copy

class MyClass:
    def __init__(self, x):
        self.x = x
original = MyClass([1, 2])
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
original.x.append(3)
print("Original:", original.x)
print("Shallow copy:", shallow_copy.x)
print("Deep copy:", deep_copy.x)

Output:

Original: [1, 2, 3]
Shallow copy: [1, 2, 3]
Deep copy: [1, 2]

Example 7: Tuple Copy

original = (1, 2, [3, 4])
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
original[2].append(5)
print("Original:", original)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)

Output:

Original: (1, 2, [3, 4, 5])
Shallow copy: (1, 2, [3, 4, 5])
Deep copy: (1, 2, [3, 4])

Example 8: Set Copy

original = {1, 2, 3}
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
original.add(4)
print("Original:", original)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)

Output:

Original: {1, 2, 3, 4}
Shallow copy: {1, 2, 3, 4}
Deep copy: {1, 2, 3}

Example 9: Multi‑Level Nesting

original = [1, {'a': 2, 'b': [3, 4]}, 5]
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
original[1]['b'].append(5)
print("Original:", original)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)

Output:

Original: [1, {'a': 2, 'b': [3, 4, 5]}, 5]
Shallow copy: [1, {'a': 2, 'b': [3, 4, 5]}, 5]
Deep copy: [1, {'a': 2, 'b': [3, 4]}, 5]

Example 10: Custom Copy Method

class MyClass:
    def __init__(self, x):
        self.x = x
    def custom_copy(self):
        return MyClass(self.x[:])
original = MyClass([1, 2])
shallow_copy = original.custom_copy()
original.x.append(3)
print("Original:", original.x)
print("Shallow copy:", shallow_copy.x)

Output:

Original: [1, 2, 3]
Shallow copy: [1, 2]

Conclusion

These examples demonstrate that a shallow copy duplicates only the top‑level object, while a deep copy recursively copies every nested element. Selecting the appropriate copy method when building API automation tests leads to more reliable and maintainable test cases.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonAutomationtestingData Structuresdeep copycopy moduleshallow copy
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.