結論
pythonで2次元配列を初期化する場合は*演算子ではなくforを使用する。
# X
lst2d = [[0] * 3] * 3
# O
lst2d = [[0] * 3 for i in range(3)]
内容
listの初期化時に*演算子を使用すると、任意の長さで配列を初期化できる。
lst1d = [0] * 3
print(lst1d)
[0, 0, 0]
2次元配列で*演算子を使って初期化すると、[1][1]に値を代入した時に[0][1]や[2][1]にも同じ値が入ってしまう。
lst2d = [[0] * 3] * 3
print(lst2d)
lst2d[1][1] = 1
print(lst2d)
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
*演算子は指定した要素を複製する。
そのため[0] * 3
は0を3つ複製し、長さ3の整数配列([0,0,0])となる。
一方[[0] * 3] * 3
は、長さ3の配列を複製するのではなく、長さ3の配列のポインタを複製しているため、値を共有してしまう。
[[0] * 3] * 3
は、長さ3の配列を3つ作るのではなく長さ3の配列のポインタを3つ作るため、lst2d[0],lst2d[1],lst2d[2]とで値を共有してしまう。
2次元配列を初期化する時、外側は*演算子ではなくforを使用する。
lst2d = [[0] * 3 for i in range(3)]
print(lst2d)
lst2d[1][1] = 1
print(lst2d)
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]