罠にはまったのでメモしておく。
簡単に言えば、Pythonの[0] * 4
は浅いコピーになるのでリストなどをコピーして生成すると死ぬ。
リストでやるとどうなるかというと、以下のようになる。
>>> l = [[0]*4]*4
>>> l[0][0] = 1
>>> print(l)
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
要素のリストの最初の値が全部書き換えられているのが確認できる。
気を付けよう。
代替案
とりあえず内包表記でやるのが一番シンプルだろうか?
l = [[0 for i in range(4)] for j in range(4)]
これなら問題なく値の更新ができる。少し長くなるけど。
forを使うなら以下のようになる。
l = []
for i in range(4):
l.append([0] * 4)
リストの中身が数値なら浅いコピーにならないので、内側のリストの生成には[0]*4
が使える。
0で初期化する場合はどちらとも同じくらいの速さでリストを生成できた。
インデックスから値を生成するようにした場合だとリスト内包表記の方が速い。
基本的にはリスト内包表記を使うようにすれば問題ないと思う。
標準関数にありそうだけど見つからない。