When I first learned Python's copy() method, I assumed it created a completely independent copy of a list.
But then I came across this example:
x = [[1], [2]]
y = x.copy()
y.append([3])
print(x)
print(y)
Output:
[[1], [2]]
[[1], [2], [3]]
At first glance, everything looked fine.
y had an extra element, while x remained unchanged.
So I thought:
"Great! copy() creates a completely new list."
But then I tried another example.
x = [[1], [2]]
y = x.copy()
y[0].append(100)
print(x)
print(y)
Output:
[[1, 100], [2]]
[[1, 100], [2]]
Wait...
Why did x change as well?
The answer lies in references.
A Python list doesn't store objects directly.
Instead, it stores references to objects.
When we use:
y = x.copy()
Python creates a new outer list, but the elements inside are not copied.
The new list still refers to the same inner objects.
A simplified memory diagram looks like this:
x ──► Outer List
│
├──► [1]
└──► [2]
y ──► New Outer List
│
├──► [1]
└──► [2]
Notice something interesting?
The outer lists are different.
The inner lists are the same.
That's exactly what a shallow copy means.
Why does append([3]) behave differently?
When we write:
y.append([3])
Python creates a brand new list object [3] and adds its reference only to y.
The original outer list x never receives that reference.
That's why only y changes.
The key takeaway
A shallow copy copies the container, not the objects inside it.
If those inner objects are mutable (like lists), modifying them will affect every reference pointing to them.
What I learned
Before learning this concept, I used to think variables stored values.
Now I think differently.
Variables refer to objects.
Lists store references.
And understanding that small difference makes many Python behaviors much easier to explain.
Sometimes learning programming isn't about memorizing methods.
It's about understanding what's actually happening behind the scenes.
Top comments (0)