Reputation: 1837
When I execute the following commands, I expect to get a 3x3 matrix (list of lists) where all cells are zero and the central cell is a one. Instead, I get a matrix where the [0][1], [1][1], and [2][1] positions are all one:
a = [[0]*3]*3
a[1][1] = 1
This seems to suggest that all of the cells in the matrix are pointing to the same object, which is confirmed by the fact that a[0] is a[1]
returns "True". Indeed, a[0][0] is a[0][1]
also returns "True" if performed before the second expression above. So, why aren't a[0][0], a[0][2], etc (the cells in the first and third "columns") also being updated with the new value?
Upvotes: 3
Views: 130
Reputation: 1123
a[0][0] is a[0][1] is comparing the value at this index (the zero). it is the same (integer) object.
But a[0][1] = 1 change the object the [0][1] location points to. The containing list aka a[0] doesn't change, only the pointed content does.
If you consider the indexes as references to objects, this is quite clear. a[0][0] is a[0][1] means both reference the same object. a[0][1] = 1 means setting the index to reference the "1" integet object.
Upvotes: 0
Reputation: 353009
This is a variant of one of the most common Python questions ever, but since the actual question here
So, why aren't a[0][0], a[0][2], etc (the cells in the first and third "columns") also being updated with the new value?
is a little different I won't vote to close.
This happens because a[0] is a[1]
and a[0][0] is a[0][1]
are a little different. The first is doing what you think it's doing: it's checking whether the two lists, a[0]
and a[1]
are the same list -- whether those are two names for the same list. The second, though, isn't checking whether a[0][0]
and a[0][1]
point to the same entry in the list -- it's saying whether the object referred to by a[0][0]
, namely the integer 0, is the same as the object referred to by a[0][1]
, which is also 0.
This could actually return False. In practice it returns True because CPython reuses small integer objects, but that's not guaranteed.
So your two "is" checks aren't quite the same: while they both test the identity of the referenced object, the second test doesn't have the same pointer-like implications in this situation.
Upvotes: 3
Reputation: 500227
The following will do what you're expecting:
a = [[0]*3 for i in range(3)]
The problem is that in your example the three top-level elements of a
end up referencing the same list, so when you change one row of a
, all other rows appear to change too.
The code I am proposing changes that, by creating three separate lists for the rows of a
.
Upvotes: 5