When working with mutable objects (like lists, dictionaries, sets, etc.), copying them can behave differently depending on how deep the copy goes.
Python provides two main ways to copy objects:
βœ… Shallow Copy
βœ… Deep Copy

Let’s understand both with clear examples and visuals πŸ‘‡


πŸ”Ή 1. What is a Copy in Python?

When you assign one variable to another:

a = [1, 2, 3]
b = a

➑️ Both a and b point to the same memory location.
If you modify b, a will change too β€” because no actual copy is made.

Example:

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

Output:

[1, 2, 3, 4]

βœ… Both a and b refer to the same list.

To actually copy objects, you can use:

  • Shallow Copy β†’ copy.copy(obj)
  • Deep Copy β†’ copy.deepcopy(obj)

πŸ”Ή 2. Import the copy Module

Before using either, you need:

import copy

πŸ”Ή 3. Shallow Copy

A shallow copy creates a new object, but does not create copies of nested objects inside it.
Instead, it just copies references to the inner objects.

βœ… Syntax:

copy.copy(object)

🧩 Example: Shallow Copy of Nested List

import copy

original = [[1, 2, 3], [4, 5, 6]]
shallow = copy.copy(original)

shallow[0][0] = 99
print("Original:", original)
print("Shallow:", shallow)

Output:

Original: [[99, 2, 3], [4, 5, 6]]
Shallow: [[99, 2, 3], [4, 5, 6]]

βœ… Changing the inner list in shallow also changed original β€”
because nested objects were not copied, only referenced.


🧠 Visualization:

original β†’ [[1, 2, 3], [4, 5, 6]]
             ↑        ↑
             └── shared β”€β”˜ (same nested lists)

shallow β†’ [[1, 2, 3], [4, 5, 6]]

Both original and shallow share the same inner lists.


🧩 However, modifying the top-level list works independently:

shallow.append([7, 8])
print("Original:", original)
print("Shallow:", shallow)

Output:

Original: [[99, 2, 3], [4, 5, 6]]
Shallow: [[99, 2, 3], [4, 5, 6], [7, 8]]

βœ… The outer list is different (copied),
but inner lists still share memory.


πŸ”Ή 4. Deep Copy

A deep copy creates a completely independent copy of the original object β€”
including all nested objects.

That means any modification in one object will not affect the other.

βœ… Syntax:

copy.deepcopy(object)

🧩 Example: Deep Copy of Nested List

import copy

original = [[1, 2, 3], [4, 5, 6]]
deep = copy.deepcopy(original)

deep[0][0] = 99
print("Original:", original)
print("Deep Copy:", deep)

Output:

Original: [[1, 2, 3], [4, 5, 6]]
Deep Copy: [[99, 2, 3], [4, 5, 6]]

βœ… Changes made to deep do not affect original.
All nested elements are fully cloned.


🧠 Visualization:

original β†’ [[1, 2, 3], [4, 5, 6]]
             ↑        ↑
deep     β†’ [[1, 2, 3], [4, 5, 6]]

βœ… Completely new objects at all levels β€” no shared references.


πŸ”Ή 5. Shallow vs Deep Copy β€” Side-by-Side Example

import copy

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

shallow = copy.copy(original)
deep = copy.deepcopy(original)

# Modify inner list
original[0][0] = 99

print("Original:", original)
print("Shallow:", shallow)
print("Deep:", deep)

Output:

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

βœ… Only the deep copy remains unaffected.


πŸ”Ή 6. Shallow Copy Using Built-in Methods

You can create shallow copies using:

list.copy()
list[:]
copy.copy()

Example:

a = [1, 2, 3]
b = a.copy()       # shallow copy
c = a[:]           # shallow copy
print(a == b == c) # True
print(a is b)      # False (different objects)

βœ… Works fine for 1D lists (no nesting).
But not safe for nested structures β€” still shares references.


πŸ”Ή 7. Performance Note

OperationSpeedMemory Usage
Shallow Copy🟒 FastLow
Deep CopyπŸ”΄ SlowerHigh (copies all nested data)

βœ… Use shallow copy when you only need a duplicate of the outer object.
βœ… Use deep copy when you need a fully independent copy of nested structures.


🧾 Summary Table

FeatureShallow CopyDeep Copy
Functioncopy.copy()copy.deepcopy()
Copies Outer Object?βœ… Yesβœ… Yes
Copies Inner Objects?❌ No (references only)βœ… Yes (new copies)
Independent?PartiallyCompletely
SpeedFasterSlower
Memory UsageLessMore
Example EffectChange in nested list affects bothChanges isolated
Use WhenNested data won’t be modifiedIndependent copy needed

πŸ”Ή 8. Real-Life Example β€” Students’ Marks

import copy

students = [["Alice", [85, 90]], ["Bob", [75, 80]]]

shallow = copy.copy(students)
deep = copy.deepcopy(students)

# Modify one student’s marks
students[0][1][0] = 100

print("Original:", students)
print("Shallow:", shallow)
print("Deep:", deep)

Output:

Original: [['Alice', [100, 90]], ['Bob', [75, 80]]]
Shallow: [['Alice', [100, 90]], ['Bob', [75, 80]]]
Deep: [['Alice', [85, 90]], ['Bob', [75, 80]]]

βœ… shallow reflects the inner list change;
βœ… deep remains untouched.


βœ… In short:

  • Shallow Copy (copy.copy())
    β†’ Copies the object, but shares nested references.
  • Deep Copy (copy.deepcopy())
    β†’ Creates a fully independent clone of the object, including nested ones.

🧩 Final Example (Quick Recap)

import copy

data = [[1, 2, 3], [4, 5, 6]]

shallow = copy.copy(data)
deep = copy.deepcopy(data)

data[0][0] = 999

print("Original:", data)
print("Shallow:", shallow)
print("Deep:", deep)

Output:

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

βœ… Shallow copy shares nested references.
βœ… Deep copy makes a complete, independent clone.


Scroll to Top