Pythonで空リストを作ったときに不思議なことに出会った。
いま、空のリストをN個もつようなリストをつくるとする。
このとき、以下の2つの方法がある。
test.py
l1 = [[]] * N
l2 = [[] for _ in range(N)]
どちらも出力すると同じリストを作成しているように見える。
>>> N = 10
>>> l1 = [[]] * N
>>> l2 = [[] for _ in range(N)]
>>> print(l1)
[[], [], [], [], [], [], [], [], [], []]
>>> print(l2)
[[], [], [], [], [], [], [], [], [], []]
しかし、要素をappendした際に違う挙動を示す。
それぞれのindex = 0 の要素に[1,2]をappendしてみよう。
>>> l1[0].append([1,2])
>>> l2[0].append([1,2])
>>> print(l1)
[[[1, 2]], [[1, 2]], [[1, 2]], [[1, 2]], [[1, 2]], [[1, 2]], [[1, 2]], [[1, 2]], [[1, 2]], [[1, 2]]]
>>> print(l2)
[[[1, 2]], [], [], [], [], [], [], [], [], []]
l1 ではすべての要素に対してappendが効いている。
どうやら、append等の操作ではコピー元の要素に対しても更新が及んでしまうらしい。
こうしたややこしいことがあるので、空の配列を作るときは
l = [[] for _ in range(N)]
とするのが無難ですね。