Python中的淺複製和深複製操作
在Python中,變數只是一個對物件的引用。因此,當它被賦值給另一個變數時,它不會複製物件,而是充當對同一物件的另一個引用。這可以使用`id()`函式來驗證。
>>> L1 = [1,2,3] >>> L2 = L1 >>> id(L1), id(L2) (2165544063496, 2165544063496)
上述程式碼的結果顯示,兩個列表物件的`id()`相同,這意味著它們都指向同一物件。L2被稱為L1的淺複製。由於兩者都指向同一物件,任何一個的更改都會反映在另一個物件中。
>>> L1 = [1,2,3] >>> L2 = L1 >>> L2[1] = 100 >>> L1,L2 ([1, 100, 3], [1, 100, 3])
在上面的例子中,L2中索引號為1的項已更改。我們看到此更改同時出現在兩者中。
當建立一個全新的物件並進行復制操作時,巢狀物件的副本也會遞迴地新增到其中,則該副本被稱為深複製。
Python標準庫的`copy`模組提供了兩種方法:
- `copy.copy()` – 建立淺複製
- `copy.deepcopy()` – 建立深複製
淺複製建立一個新物件並存儲原始元素的引用,但不建立巢狀物件的副本。它只複製巢狀物件的引用。結果,複製過程不是遞迴的。
>>> import copy >>> L1 = [[1,2,3], [4,5,6]] >>> L2 = copy.copy(L1) >>> L1,L2 ([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]) >>> L2.append([10,10,10]) >>> L1,L2 ([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6], [10, 10, 10]])
這裡L1是一個巢狀列表,L2是它的淺複製。雖然對父列表物件的引用被複制到L2中,但它的巢狀元素並沒有被複制。因此,當我們將另一個列表新增到L2時,它不會反映在L1中。
但是,如果我們嘗試修改子元素中的元素,其影響將在兩個列表中都看到。
>>> L1 = [[1,2,3], [4,5,6]] >>> L2 = copy.copy(L1) >>> L1,L2 ([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]) >>> L2[1][0] = 100 >>> L1,L2 ([[1, 2, 3], [100, 5, 6]], [[1, 2, 3], [100, 5, 6]])
然而,深複製建立一個新物件,並遞迴地新增原始元素中存在的巢狀物件的副本。
在下面的例子中,L2是L1的深複製。現在,如果我們更改內部列表的任何元素,這將不會顯示在另一個列表中。
>>> L1 = [[1,2,3], [4,5,6]] >>> L2 = copy.deepcopy(L1) >>> L1,L2 ([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]) >>> L2[1][0] = 100 >>> L1,L2 ([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [100, 5, 6]])
輸出驗證了深複製的效果。
廣告