I was trying to create a simple 2-D array in Python today. No numpy, no pandas, just the simpliest kind using the default list data structure.
Normally, to create a n by n 2-D array with all zeros, I would just do it through list comprehension:
[[0 for i in range(n)] for j in range(n)]
Today I thought, what could possibly go wrong if I use the cool trick that works great with creating 1-D arrays?
If you are trying to create an 1-D array with all zeros, a common shortcut is
 * n
Now, for 2-D array, I did
[ * n] * n
However, when I run my program, it did not work as expected. For example, for a 3x3 array of all zeros, when I change array to 1, I expect to see
1 0 0 0 0 0 0 0 0
Instead, I got:
1 0 0 1 0 0 1 0 0
So what happened? Let’s talk about mutable objects first. Python mutability refers to being able to change an object. Simply put, a mutable object can be changed, but an immutable object cannot. Dictionaries, sets, and lists are mutable. When you change a mutable object, this is what happens:
a = [0, 0, 0] b = a b = 1 print(a) > [1, 0, 0]
In our case, in the 2-D array, all rows are referring to the same mutable list object I created in the inner
 * n code segment. Because lists are mutable, and array, array, … are all referencing to the same list, when I changed the value of the list in one place, the change will propagate to all other places. This was not an issue when we use the same method to create 1-D arrays, as integer types are immutable.