print(knowledge)

アウトプット帳

pythonで二次元配列を初期化するときの注意

はじめに

最近python競技プログラミングをやっていて、2次元配列の挙動で注意しておかないといけないことを見つけたのでメモ。

環境

説明

>>>インタラクティブモードのアレです

1次元配列

pythonでは以下のように配列を初期化できる

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

要素の変更も容易にできる

>>> d[0] = 1
>>> d
[1, 0, 0]

2次元配列

しかし、二次元配列となると話が変わってくる

内側の配列の要素を一つだけ変えようとすると他の配列の要素も変わってしまう

>>> l = [[0]*2]*3
>>> l
[[0, 0], [0, 0], [0, 0]]
>>> l[0][1] = 1
>>> l
[[0, 1], [0, 1], [0, 1]]

id関数でオブジェクトのIDを見てみると、内側の配列のIDが同じことが分かる。

つまり、内側の配列のオブジェクトは全て同じ場所を参照しているので、どれかを変更すると他の配列も変更されてしまう。

>>> id(l[0])
4319671496
>>> id(l[1])
4319671496

対策

これを防ぐには、内包表記で初期化するのが良いだろう

>>> l = [[0]*2 for _ in range(3)]
>>> l
[[0, 0], [0, 0], [0, 0]]
>>> l[0][0] = 1
>>> l
[[1, 0], [0, 0], [0, 0]]

内側の配列のIDが違うことも確認できる

>>> id(l[0])
4320008648
>>> id(l[1])
4320008392

終わりに

pythonで二次元配列を初期化するときは気をつけよう。