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]])

輸出驗證了深複製的效果。

更新於:2019年7月30日

457 次瀏覽

啟動您的職業生涯

完成課程獲得認證

開始學習
廣告