Python創建二維列表的正確姿勢
簡介
Python中沒有數組,使用list
結構代替,並且list
結構的功能更加強大:
- 支持動態擴容,無需擔心元素過量
- 對list內的元素類型不做一致性約束
- 提供豐富的方法:pop、insert、sort、index等等
- ...
list
也是我們最常使用的一種結構,我們也需要了解它的一些特性,學會正確使用它。
探索列表的初始化
初始化一維列表
>>> month = ["January", "February", "March"]
初始化二維列表
>>> row, col = 3, 4
>>> right_matrix = [[0] * col for _ in range(row)]
>>> wrong_matrix = [[0] * col] * row
>>> print(right_matrix)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> print(wrong_matrix)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
看似兩種方式初始化出的二維列表是一樣的,但為啥第二種是wrong_matrix
呢?它會有問題呢?
如果我們嘗試更新試試
>>> right_matrix[0][0] = 1
>>> print(right_matrix)
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] # 正常
>>> wrong_matrix[0][0] = 1
>>> print(wrong_matrix)
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]] # 不正常,每行第一列都被更新成了1
分析兩種初始化方式的內存情況
率先想到的是list
屬於可變數據結,在函數傳遞過程中容易發生淺拷貝
(在函數內部的更改不會影響函數外部該變量的值)。
>>> id(right_matrix[0]), id(right_matrix[1]), id(right_matrix[2])
(288926611776, 288926609600, 288926609472)
>>> id(wrong_matrix[0]), id(wrong_matrix[1]), id(wrong_matrix[2])
(288926610176, 288926610176, 288926610176)
使用id()
函數可以獲取對象的內存id,發現right_martix
中每行的id是不同的,它們都是獨立的list對象,而wrong_matrix
中每行的id是相同的,它們是同一個lsit對象,所以會出現上面的情況:目的是改wrong_matrix[0][0]
,但實際上wrong_matrix[1][0]
和wrong_martix[2][0]
也被修改了。
使用http://pythontutor.com/visualize.html#mode=edit 網站執行上面的right_matrix
和wrong_matrix
代碼來對比實際的內存情況,來驗證一下
right_matrix
:
wrong_matrix
:
right_matrix
中每個list對象都有獨立的內存空間,而wrong_matrix
中每個list對象指向同一塊內存空間。
結論
list的元素如果是可變數據類型,一定要用方法一的方式初始化
>>> row, col = 3, 4
>>> right_matrix = [[0] * col for _ in range(row)]
這種方式下,right_matrix
里的每個list對象都有獨立的內存空間,不會出現修right_matrix[0][0]
,right_matrix[1][0]
和right_martix[2][0]
也被修改的情況。