Pythonの多次元リストの初期化

Pythonの多次元リストの作成方法について調べたので、自分用にメモ

まずは、1次元リストの初期化

>>> map(lambda i:0, range(3))
[0, 0, 0]
>>> [0]*3
[0, 0, 0]

次に2次元リストの初期化<内包表記を使った場合>

>>> a = [[0 for i in range(3)] for i in range(3)]
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

<*を使った場合>

>>> b = [[0]*3]*3
>>> b
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

ここまでは、同じように内包表記、*を使った書き方、どちらとも同じ結果が得られます。
次に、要素[0][0]の値を1に変更してみましょう。<内包表記を使った場合>

>>> a[0][0] = 1
>>> a
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]

<*を使った場合>

>>> b[0][0] = 1
>>> b
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]

すると、*を使った初期化では要素[1][0]、[2][0]まで値が変更してしまいます。
これは生成されたリストの要素が全て同じインスタンスを参照していることが原因のため要注意です。
ただ、上記のように内包表記を使った多次元リストの初期化はfor文を2度書いているので、もう少し簡潔に書きたいですよね。

1次元リストを作成するときには*を使って、2次元以降には内包表記で書くと以下のようにすっきりしました。

>>> c = [[0] * 3 for i in range(3)]
>>> c
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> 
>>> c[0][0] = 1
>>> c
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]