When a Python List Copy Is Only Half a Copy
You used .copy(), but changing your copied data still affected the original.
Did the copy fail?
The answer depends on what is inside your list. A shallow copy creates a new outer list, while its elements still refer to the same objects.
Let’s explore this through a weekly schedule.
1. Adding a day keeps the original unchanged
schedule = [
["Monday", "Python"],
["Tuesday", "SQL"],
]
revised = schedule.copy()
revised.append(["Wednesday", "Git"])
print(len(schedule))
print(len(revised))
Output:
2
3
Calling .copy() created a separate outer list.
Appending a new entry changes only revised. So far, the copy behaves exactly as you might expect.
2. Editing an existing day affects both lists
Now start again and update Monday’s subject:
schedule = [
["Monday", "Python"],
["Tuesday", "SQL"],
]
revised = schedule.copy()
revised[0][1] = "JavaScript"
print(schedule[0])
print(revised[0])
Output:
['Monday', 'JavaScript']
['Monday', 'JavaScript']
The outer lists are separate, but their first elements refer to the same inner list.
This expression:
revised[0][1] = "JavaScript"
accesses that shared inner list and replaces one of its elements.
You can inspect the relationship directly:
print(schedule is revised)
print(schedule[0] is revised[0])
Output:
False
True
3. Replacing a whole entry behaves differently
Compare the previous example with this one:
schedule = [
["Monday", "Python"],
["Tuesday", "SQL"],
]
revised = schedule.copy()
revised[0] = ["Monday", "JavaScript"]
print(schedule[0])
print(revised[0])
Output:
['Monday', 'Python']
['Monday', 'JavaScript']
Here, we create a new inner list and place it into the separate outer list revised.
The original Monday entry remains unchanged.
The difference is the level at which the assignment happens:
| Statement | What changes? |
|---|---|
revised[0][1] = "JavaScript" |
An element inside the shared inner list |
revised[0] = ["Monday", "JavaScript"] |
An element inside the separate outer list |
4. Copying each row can provide enough independence
For this schedule, we can copy both the outer list and each row:
schedule = [
["Monday", "Python"],
["Tuesday", "SQL"],
]
revised = [row.copy() for row in schedule]
revised[0][1] = "JavaScript"
print(schedule[0])
print(revised[0])
Output:
['Monday', 'Python']
['Monday', 'JavaScript']
The list comprehension builds a new outer list. Each row.copy() also creates a new row.
This works for our schedule because each row contains strings. It does not recursively copy every possible level of nested data.
5. Another nesting level introduces sharing again
Suppose each day contains a list of subjects:
schedule = [
["Monday", ["Python", "SQL"]],
["Tuesday", ["Git"]],
]
revised = [row.copy() for row in schedule]
revised[0][1].append("Testing")
print(schedule[0][1])
print(revised[0][1])
Output:
['Python', 'SQL', 'Testing']
['Python', 'SQL', 'Testing']
We copied the outer list and each row, but the subject lists inside those rows remain shared.
When this nested data needs to be independent, use deepcopy():
from copy import deepcopy
schedule = [
["Monday", ["Python", "SQL"]],
["Tuesday", ["Git"]],
]
revised = deepcopy(schedule)
revised[0][1].append("Testing")
print(schedule[0][1])
print(revised[0][1])
Output:
['Python', 'SQL']
['Python', 'SQL', 'Testing']
For this structure, the nested subject lists are now independent.
Choose the copy that matches your change
Before copying a list, consider what you intend to modify.
- Adding or removing outer entries: a shallow copy may be enough.
- Editing individual rows: copying each row may be enough for simple data.
- Changing mutable objects deeper inside the structure: consider a deep copy.
The useful question is: Which objects will my next operation modify, and are those objects still shared?
For further reading, see the official Python documentation on shallow and deep copying.
Free PCEP practice test
Preparing for PCEP? Explore my AM Academy free practice test here: https://www.udemy.com/course/python-pcep-30-03-certification-practice-tests-2026/?couponCode=FREE-COURSE-PCEP. I’m the creator of this independent preparation resource; it is not affiliated with or endorsed by the Python Institute.
Top comments (0)