🧬 Python Tutorial β€” Shallow Copy vs Deep Copy

Introduction 🌟

When copying objects in Python, it's important to understand the difference betweenshallow copy and deep copy. Both create new objects β€” but they behave very differently with nested (mutable) data.

Note

πŸ’‘ Shallow Copy β†’ Copies only the outer object
πŸ’‘ Deep Copy β†’ Copies the outer object + all nested objects

1. Importing the copy Module 🧱

import_copy.py

import copy

2. What is a Shallow Copy? πŸͺž

A shallow copy creates a new object, but **nested mutable objects are shared (not copied)**.

Using copy.copy()

shallow_basic.py

import copy

a = [1, 2, [3, 4]]
b = copy.copy(a)

b[0] = 100    # modifies only b
b[2][0] = 999 # modifies the shared nested list

print("a =", a)
print("b =", b)

βœ” Outer list is copied
βœ” Inner list is shared β†’ shallow copy problem

3. What is a Deep Copy? πŸ§ͺ

A deep copy creates a fully independent clone: all nested lists, dictionaries, sets, and objects are copied recursively.

Using copy.deepcopy()

deep_basic.py

import copy

a = [1, 2, [3, 4]]
b = copy.deepcopy(a)

b[2][0] = 999  # modifies only b's nested list

print("a =", a)
print("b =", b)

βœ” Completely independent copy

4. Visual Difference πŸ“Š

OperationShallow CopyDeep Copy
Create new outer object?YesYes
Copy nested objects?NoYes
Nested changes affect original?YesNo
PerformanceFasterSlower (copies everything)

5. Shallow Copy Examples πŸ”

Shallow Copy of a List

shallow_list.py

a = [[1,2], [3,4]]
b = a.copy()     # list’s own shallow copy

b[0][1] = 999
print(a)  # nested list changed in a
print(b)

Shallow Copy of a Dictionary

shallow_dict.py

d1 = {"a": 1, "b": [10, 20]}
d2 = d1.copy()

d2["b"][0] = 999
print(d1)   # original changed!
print(d2)

6. Deep Copy Examples 🧠

Deep Copy of List

deep_list.py

import copy

a = [[1,2], [3,4]]
b = copy.deepcopy(a)

b[0][1] = 999
print(a)  # unchanged
print(b)

Deep Copy of Dictionary

deep_dict.py

import copy

d1 = {"a": 1, "b": [10, 20]}
d2 = copy.deepcopy(d1)

d2["b"][0] = 999
print(d1)  # unchanged
print(d2)

7. When to Use Which? 🧩

  • βœ” Use **shallow copy** for simple, non-nested data
  • βœ” Use **deep copy** for complex nested structures
  • βœ” Avoid deep copy when performance is critical

Note

⚠️ Deep copy may fail for objects holding external resources (like file handlers or network connections).

8. Special Case β€” Immutable Types 🧊

Immutable objects (int, float, str, tuple) are always safe: copying them behaves the same as assignment.

immutable_copy.py

x = 10
y = copy.copy(x)
z = copy.deepcopy(x)

print(x == y == z)  # True

9. Real-World Example β€” Avoid Shared References ⚠️

reference_issue.py

a = [[0] * 3] * 3   # BAD: all rows share same list

a[0][0] = 999
print(a)  # all rows modified!

βœ” Use deep copy or list comprehension to avoid this issue

10. Real-World Example β€” Safe Copying of Configurations βš™οΈ

config_copy.py

import copy

default_config = {
    "theme": "dark",
    "options": {"font": "Arial", "size": 12}
}

user_config = copy.deepcopy(default_config)
user_config["options"]["size"] = 18

print(default_config)  # unchanged
print(user_config)

Cheat Sheet πŸ“˜

Copy TypeFunctionCopies Nested Objects?
Shallow Copycopy.copy()No
Deep Copycopy.deepcopy()Yes
List Shallow Copylist.copy()No
Dict Shallow Copydict.copy()No

Conclusion πŸŽ‰

>>β€œShallow copy copies structure β€” deep copy copies the structure and all its contents.” ✨

You now fully understand Shallow Copy vs Deep Copy in Python! Want the next topic? Try Mutable vs Immutable Objects, Garbage Collection, or Memory Management. Just tell me! 😊