Python 如何正確初始化二維陣列

筆者在最近的需求裡遇到需要宣告二維陣列的狀況
但卻發現資料為什麼怎麼塞都不對…

此篇文章分享給你各位,如何正確的初始化你各位的二維陣列

問題

一開始是這樣的,一切就是這麼簡潔這麼美,如此的 Pythonic

1
test_list = [[]] * 3

但結果發現無論我在哪個維度塞資料
都會在所有陣列上看到所有結果

1
2
3
4
5
test_list = [[]] * 3
test_list[0].append(0)

for l in test_list:
print(l)

執行結果

1
2
3
[0]
[0]
[0]

WTF?
image 16

接著我把物件的 id 全部印出來

1
2
3
4
test_list = [[]] * 3

for l in test_list:
print(id(l))

結果發現

1
2
3
4307825408
4307825408
4307825408
image 17

Why? 到底是為什麼?

結論

經過一番追尋之後,終於在官方文件 Sequence Types 找到答案

其中,有一段很重要的提醒

Note that items in the sequence s are not copied; they are referenced multiple times. This often haunts new Python programmers;

同時也演示了問題發生的程式碼

1
2
3
4
5
6
>>> lists = [[]] * 3
>>> lists
[[], [], []]
>>> lists[0].append(3)
>>> lists
[[3], [3], [3]]

同時也推薦你各位用以下方式初始化

1
2
3
4
5
6
>>> lists = [[] for i in range(3)]
>>> lists[0].append(3)
>>> lists[1].append(5)
>>> lists[2].append(7)
>>> lists
[[3], [5], [7]]

如果你有 y, x 這樣的需求,可以用以下方式初始化

1
2
3
4
5
6
7
y = 3
x = 4

test_list = [[0] * x for _ in range(y)]

# test_list[y][x]
test_list[y - 1][x - 1] = 1

而官方也出了一篇 FAQ 專門講這件事
How do I create a multidimensional list?

追尋至此終於宣告破案…

也許你也會想看看