I recently ran into a weird Python bug while solving a problem that needed a 2D list.
Everything looked correct, but the output was completely wrong.
Turns out, it was this one line:
index = [[0, 0]] * n
If you’ve written Python for a while, you might already know where this is going.
What I Thought This Did
I thought this would create n rows, each with [0, 0].
Something like:
[
[0, 0],
[0, 0],
[0, 0]
]
Reasonable assumption.
Totally wrong assumption.
What It Actually Does
Python doesn’t create n separate lists here.
It creates one list [0, 0]
and then repeats the reference to it n times.
So all rows point to the same object.
Here’s the proof:
index = [[0, 0]] * 3
index[0][0] = 7
print(index)
Output:
[[7, 0], [7, 0], [7, 0]]
I changed one value… and every row changed.
That’s when I knew something was off.
Why This Happens
The * operator does a shallow copy.
Internally, Python is basically doing:
index = [same_list, same_list, same_list]
So modifying one row means modifying all of them.
The Fix (And the Right Way)
The correct way is using a list comprehension:
index = [[0, 0] for _ in range(n)]
This creates new lists every time, not shared ones.
Quick check:
index = [[0, 0] for _ in range(3)]
index[0][0] = 7
print(index)
Output:
[[7, 0], [0, 0], [0, 0]]
Exactly what we want.
When * Is Actually Fine
Using * is totally okay with immutable values:
arr = [0] * 5 # perfectly fine
The problem only starts when you use it with nested mutable objects like lists.
Top comments (0)