In Python, lists are mutable, meaning their contents can be changed. A common mistake occurs when you try to copy a list using assignment (=
) instead of using the copy()
method or copy
module. This leads to unexpected behavior, where modifying one list affects the other because both refer to the same memory location.
Let’s go step by step to understand the issue and how to avoid it.
1. Understanding List Assignment (=
)
When you assign a list to another variable using =
, you are not creating a new list; instead, you are creating a reference to the same list in memory.
Example: Incorrect List Copying Using =
list1 = [1, 2, 3, 4]
list2 = list1 # Creates a reference, not a copy
list2.append(5) # Modifying list2 also affects list1
print(list1) # Output: [1, 2, 3, 4, 5]
print(list2) # Output: [1, 2, 3, 4, 5]
Problem:
list1
andlist2
share the same memory address.- Any modification to
list2
also modifieslist1
, which is usually not intended.
Check Memory Address
print(id(list1)) # Memory address of list1
print(id(list2)) # Memory address of list2 (same as list1)
2. Correct Ways to Copy a List
Method 1: Using copy()
(Shallow Copy)
The built-in copy()
method creates a new list but only copies the outer elements (shallow copy).
list1 = [1, 2, 3, 4]
list2 = list1.copy() # Proper copy
list2.append(5)
print(list1) # Output: [1, 2, 3, 4] (Unchanged)
print(list2) # Output: [1, 2, 3, 4, 5] (New list)
Memory addresses are different:
print(id(list1)) # Different memory address
print(id(list2))
Method 2: Using list()
Constructor
Another way to create a shallow copy is using list()
.
list1 = [1, 2, 3, 4]
list2 = list(list1) # Creates a copy
list2.append(5)
print(list1) # [1, 2, 3, 4] (Unchanged)
print(list2) # [1, 2, 3, 4, 5] (New list)
Method 3: Using Slicing ([:]
)
A simple and efficient way to copy a list is using slicing.
list1 = [1, 2, 3, 4]
list2 = list1[:] # Copies all elements
list2.append(5)
print(list1) # [1, 2, 3, 4]
print(list2) # [1, 2, 3, 4, 5]
3. Deep Copying (for Nested Lists)
A shallow copy works for simple lists, but for nested lists (lists within lists), you need a deep copy.
Example of Shallow Copying a Nested List
list1 = [[1, 2], [3, 4]]
list2 = list1.copy() # Shallow copy (nested lists are still linked)
list2[0][0] = 100 # Modifies list1 too!
print(list1) # [[100, 2], [3, 4]]
print(list2) # [[100, 2], [3, 4]]
Problem: The outer list is copied, but nested lists still share the same reference.
Method 4: Using copy.deepcopy()
for Nested Lists
For nested lists, use copy.deepcopy()
from the copy
module.
import copy
list1 = [[1, 2], [3, 4]]
list2 = copy.deepcopy(list1) # Deep copy
list2[0][0] = 100
print(list1) # [[1, 2], [3, 4]] (Unchanged)
print(list2) # [[100, 2], [3, 4]]
Deep copy ensures that all nested lists are fully copied and do not reference the original.
4. Summary of Copying Methods
Method | Type | Works for Nested Lists? | Creates a New Memory Address? |
---|---|---|---|
= (Assignment) | Reference | No | No |
.copy() | Shallow Copy | No | Yes (outer list only) |
list() | Shallow Copy | No | Yes (outer list only) |
[:] (Slicing) | Shallow Copy | No | Yes (outer list only) |
copy.deepcopy() | Deep Copy | Yes | Yes (fully independent) |