Pythonで2次配列の初期化の仕方

python コンピュータ

要素数が3×3で配列を0で初期化したい

成功例

v = [[0] * 3 for i in range(3)]
v[1][1] = 255
print(v)
[[0, 0, 0], [0, 255, 0], [0, 0, 0]]

[0] * 3で1次配列[0,0,0]を生成し、それをforで3回繰り返すことで2次配列にしています。
ちなみにv = [[0] * 3] * 3でも0で初期化されたように見えて使い物にならない3×3の配列が出来上がります。

失敗例

v = [[0] * 3] * 3
v[1][1] = 255
print(v)
[[0, 255, 0], [0, 255, 0], [0, 255, 0]]

[0] * 3で1次配列[0,0,0]を生成するところまでは同じですが、次の*3[0,0,0]への参照をを3つ作ります。
同じ配列を参照していますので、v[1][1]の要素を書き換えるとv[0][1]とv[1][1]も同じ値が返ります。

Gimpのpython-fuスクリプトを作っている最中、範囲選択されたピクセルを配列に退避させようとした際、この失敗をしました。
最終的に画像を加工するのですが思った通りの結果にならずだいぶ悩みました。エラーが出るとか画像が加工されないとかなら、比較的バグの要因がつかみやすいのですが、中途半端に破綻した画像が出来上がり非常に厄介でした。書き換えた内容の規則性に気が付くまで配列の初期化の仕方に問題があるとは夢にも思いませんでした。
固定長の2次配列を作る機会も少ないとは思いますが、今回の失敗を忘れないようにしたいと思います。

コメント