Today, I uncovered a surprise in using repeat expression to initialize a list of lists. Although the resulted piece of data appeared to be like a list of lists initialized, when I start to modify an element in the data, the modification is duplicated across all lists (rows) that have been repeated. This could result in a nasty bug if one does not watch the actual behavior of the operation!
Here is distilled example code to demonstrate the problem.
When x is constructed as a list of lists and initialized, modifying one of its element only has the effect to that element.
x = [[0,0],
[0,0],
[0,0]] # initialized as array of arrays
x0 = x[0] # x0 = [0, 0]
x1 = x[1] # x1 = [0, 0]
x2 = x[2] # x2 = [0, 0]
x[0][0] = 1 # modify the element at row 0, and column 0
x0 = x[0] # x0 = [1, 0]
x1 = x[1] # x1 = [0, 0]
x2 = x[2] # x2 = [0, 0]
But when a seemingly the same list of lists is constructed using repeat operations, the resulted data is not really a list of lists, but just appeared to be one with the initialized constant. Once modifying one of the element, the modification would be duplicated to all the arrays (rows) of the data.
x = [[0]*2]*3 # initialized by repeat expression
# appearing of the same values of the above array of arrays
x0 = x[0] # x0 = [0, 0]
x1 = x[1] # x1 = [0, 0]
x2 = x[2] # x2 = [0, 0]
x[0][0] = 1 # modify the element at row 0, and column 0
x0 = x[0] # x0 = [1, 0] as expected
x1 = x[1] # x1 = [1, 0] not as expected!
x2 = x[2] # x2 = [1, 0] not as expected!
# It seems that the repeated expression is of the same copy of storage!
# referred by the same label/address
Furthermore, the behavior for the one-dimensional array would be different:
x = [0]*3
x0 = x[0] # x0 = 0
x1 = x[1] # x1 = 0
x2 = x[2] # x2 = 0
x[0] = 1
x0 = x[0] # x0 = 1
x1 = x[1] # x1 = 0
x2 = x[2] # x2 = 0
It might be a clever optimization.
But the moral of the story that I need to be cautious about Python's lack of consistency. In particular, the repeat expression is only meant for a constant value, never for mutable operations.
I wonder how I can learn more about those exceptional inconsistent nuances in Python?