HOWTO · Python
在 Python 中複製二維陣列
本文演示如何在 Python 中製作二維陣列的副本
本頁內容
在 Python 中複製二維資料時,請依資料型別和資料共享方式選擇操作:若要取得資料獨立的陣列,使用 NumPy 的 copy();若要讓巢狀清單中的內層清單也彼此獨立,使用 copy.deepcopy();若有意共享內層物件,則使用淺拷貝。NumPy 的 view() 會建立另一個陣列物件,但與原陣列共用底層資料。
二維陣列將值排列成列與欄。在 Python 的清單巢狀清單表示法中,每個內層清單都是一列;兩個索引依序選取列,以及該列中的元素,例如 data[row_index][column_index]。
使用 NumPy 的 copy() 方法建立二維陣列副本
對 NumPy ndarray 呼叫其 copy() 方法,可建立一個擁有獨立資料的陣列。以下範例會修改副本中的一個值,接著檢視兩個陣列:
import numpy as np
original = np.array([[23, 34, 45], [24, 45, 78]])
copied = original.copy()
copied[0, 2] = 65
print("Copy:", copied.tolist())
print("Original:", original.tolist())
Copy: [[23, 34, 65], [24, 45, 78]]
Original: [[23, 34, 45], [24, 45, 78]]
指派操作會修改 copied,原始陣列則保留初始值。若要獨立編輯數值陣列資料,這是直接合適的選擇。NumPy 陣列也可以包含 Python 物件;複製 object-dtype 陣列時,會複製陣列的資料緩衝區,但不會遞迴複製其中儲存的 Python 物件。範例輸出中的 “Copy:” 和 “Original:” 標籤維持英文,分別表示副本與原始陣列。
使用 copy.deepcopy() 函式建立二維陣列副本
對巢狀 Python 清單而言,copy.deepcopy() 會遞迴複製清單及其內容。若複製後可能會修改內層清單,這點尤其重要:
import copy
original = [["red", "blue"], ["green", "gold"]]
copied = copy.deepcopy(original)
copied[0].append("white")
print("Copy:", copied)
print("Original:", original)
Copy: [['red', 'blue', 'white'], ['green', 'gold']]
Original: [['red', 'blue'], ['green', 'gold']]
新的外層清單和內層清單都與原始清單分開,因此在 copied 的內層清單中新增元素,不會改變 original。deepcopy() 適合用於巢狀可變資料;若物件很大或屬於自訂型別,請考量遞迴複製所有參照物件是否合適。
在 Python 中建立二維陣列的淺拷貝
淺拷貝會建立新的外層容器,但仍保留指向原始內層物件的參照。對巢狀清單來說,copy.copy() 和外層清單的方法 list.copy() 都具有這種行為:
import copy
original = [["red", "blue"], ["green", "gold"]]
copied = copy.copy(original)
copied[0].append("white")
print("Copy:", copied)
print("Original:", original)
Copy: [['red', 'blue', 'white'], ['green', 'gold']]
Original: [['red', 'blue', 'white'], ['green', 'gold']]
此處兩個外層清單都參照同一個第一內層清單,因此透過任一清單都能看到新增的元素。若替換複製後外層清單中的項目,例如 copied[0] = ["black"],只會改變該外層清單中的參照。若也需要讓內層清單彼此獨立,請使用 copy.deepcopy()。
NumPy 的 view() 與巢狀 Python 清單的淺拷貝是不同操作。它會傳回另一個 ndarray 物件,但與原始陣列共用資料,因此透過檢視陣列指派值,也會改變透過原始陣列看到的值。若需要獨立的 NumPy 資料,請改用 ndarray.copy()。物件身分與資料共享是兩個不同問題:兩個陣列可以是不同物件,卻仍呈現相同的底層值。
import numpy as np
original = np.array([[24, 23, 25], [32, 43, 54]])
view = original.view()
view[0, 2] = 100
print("View:", view.tolist())
print("Original:", original.tolist())
View: [[24, 23, 100], [32, 43, 54]]
Original: [[24, 23, 100], [32, 43, 54]]