'圖解 Python 淺拷貝與深拷貝'

Python 啟迪雲Tuscloud 2019-08-31
"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


但是,因為我們只創建了原始列表的一個淺拷貝,所以 new_list 仍然包含對 lst 中存儲的原始子對象的引用。

也就是如上圖所示,lst 和 new_list 的子列表都指向了相同的對象。

子對象沒有被複制,它們只是在複製的列表中被再次引用。

因此,當你修改 lst 中的一個子對象時,這種修改也會反映到 new_list 中—— 這是因為兩個列表共享相同的子對象。這種複製只是一個淺的,一個層級的複製:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6], [7, 8, 9]]
[['x', 2, 3], [4, 5, 6]]



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


但是,因為我們只創建了原始列表的一個淺拷貝,所以 new_list 仍然包含對 lst 中存儲的原始子對象的引用。

也就是如上圖所示,lst 和 new_list 的子列表都指向了相同的對象。

子對象沒有被複制,它們只是在複製的列表中被再次引用。

因此,當你修改 lst 中的一個子對象時,這種修改也會反映到 new_list 中—— 這是因為兩個列表共享相同的子對象。這種複製只是一個淺的,一個層級的複製:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6], [7, 8, 9]]
[['x', 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


如果我們在第一步中創建了一個 lst 的深拷貝,那麼兩個對象就完全獨立了。這是對象的淺拷貝和深拷貝之間的實際區別。

使用 Python 標準庫中的 copy 模塊可以創建深拷貝,這個模塊為創建任意 Python 對象的淺拷貝和深拷貝提供了一個簡單的接口。

創建深拷貝

這次我們使用 deepcopy() 函數創建一個對象的深拷貝:

import copy
lst = [[1, 2, 3], [4, 5, 6]]
new_list = copy.deepcopy(lst)



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


但是,因為我們只創建了原始列表的一個淺拷貝,所以 new_list 仍然包含對 lst 中存儲的原始子對象的引用。

也就是如上圖所示,lst 和 new_list 的子列表都指向了相同的對象。

子對象沒有被複制,它們只是在複製的列表中被再次引用。

因此,當你修改 lst 中的一個子對象時,這種修改也會反映到 new_list 中—— 這是因為兩個列表共享相同的子對象。這種複製只是一個淺的,一個層級的複製:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6], [7, 8, 9]]
[['x', 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


如果我們在第一步中創建了一個 lst 的深拷貝,那麼兩個對象就完全獨立了。這是對象的淺拷貝和深拷貝之間的實際區別。

使用 Python 標準庫中的 copy 模塊可以創建深拷貝,這個模塊為創建任意 Python 對象的淺拷貝和深拷貝提供了一個簡單的接口。

創建深拷貝

這次我們使用 deepcopy() 函數創建一個對象的深拷貝:

import copy
lst = [[1, 2, 3], [4, 5, 6]]
new_list = copy.deepcopy(lst)



圖解 Python 淺拷貝與深拷貝


從圖中可以看出 lst 和 new_list 中的子對象指向了不同的對象,如果對 lst 的子對象進行修改,將不會影響 new_list。

這一次,原始對象和複製對象都是完全獨立的。如前面所說,遞歸克隆了 lst,包括它的所有子對象:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


但是,因為我們只創建了原始列表的一個淺拷貝,所以 new_list 仍然包含對 lst 中存儲的原始子對象的引用。

也就是如上圖所示,lst 和 new_list 的子列表都指向了相同的對象。

子對象沒有被複制,它們只是在複製的列表中被再次引用。

因此,當你修改 lst 中的一個子對象時,這種修改也會反映到 new_list 中—— 這是因為兩個列表共享相同的子對象。這種複製只是一個淺的,一個層級的複製:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6], [7, 8, 9]]
[['x', 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


如果我們在第一步中創建了一個 lst 的深拷貝,那麼兩個對象就完全獨立了。這是對象的淺拷貝和深拷貝之間的實際區別。

使用 Python 標準庫中的 copy 模塊可以創建深拷貝,這個模塊為創建任意 Python 對象的淺拷貝和深拷貝提供了一個簡單的接口。

創建深拷貝

這次我們使用 deepcopy() 函數創建一個對象的深拷貝:

import copy
lst = [[1, 2, 3], [4, 5, 6]]
new_list = copy.deepcopy(lst)



圖解 Python 淺拷貝與深拷貝


從圖中可以看出 lst 和 new_list 中的子對象指向了不同的對象,如果對 lst 的子對象進行修改,將不會影響 new_list。

這一次,原始對象和複製對象都是完全獨立的。如前面所說,遞歸克隆了 lst,包括它的所有子對象:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


copy 模塊中的 copy.copy() 函數也可以創建對象的淺拷貝。使用 copy.copy() 可以明確地表示創建淺拷貝。對於內置集合,簡單地使用 list、dict 和 set 等工廠函數來創建淺拷貝是更加 Pythonic 的。

複製任意 Python 對象

copy.copy() 和 copy.deepcopy() 函數可用於複製任意對象。以前面的列表複製示例為基礎。讓我們從定義一個簡單的 2D 點類開始:

class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x!r}, {self.y!r})'

__repr__() 函數使我們可以輕鬆地在 Python 解釋器中檢查從這個類創建的對象。

接下來,我們將創建一個 Point 實例,然後使用 copy 模塊複製(淺拷貝)它:

a = Point(23, 42)
b = copy.copy(a)
print(a is b)


False



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


但是,因為我們只創建了原始列表的一個淺拷貝,所以 new_list 仍然包含對 lst 中存儲的原始子對象的引用。

也就是如上圖所示,lst 和 new_list 的子列表都指向了相同的對象。

子對象沒有被複制,它們只是在複製的列表中被再次引用。

因此,當你修改 lst 中的一個子對象時,這種修改也會反映到 new_list 中—— 這是因為兩個列表共享相同的子對象。這種複製只是一個淺的,一個層級的複製:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6], [7, 8, 9]]
[['x', 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


如果我們在第一步中創建了一個 lst 的深拷貝,那麼兩個對象就完全獨立了。這是對象的淺拷貝和深拷貝之間的實際區別。

使用 Python 標準庫中的 copy 模塊可以創建深拷貝,這個模塊為創建任意 Python 對象的淺拷貝和深拷貝提供了一個簡單的接口。

創建深拷貝

這次我們使用 deepcopy() 函數創建一個對象的深拷貝:

import copy
lst = [[1, 2, 3], [4, 5, 6]]
new_list = copy.deepcopy(lst)



圖解 Python 淺拷貝與深拷貝


從圖中可以看出 lst 和 new_list 中的子對象指向了不同的對象,如果對 lst 的子對象進行修改,將不會影響 new_list。

這一次,原始對象和複製對象都是完全獨立的。如前面所說,遞歸克隆了 lst,包括它的所有子對象:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


copy 模塊中的 copy.copy() 函數也可以創建對象的淺拷貝。使用 copy.copy() 可以明確地表示創建淺拷貝。對於內置集合,簡單地使用 list、dict 和 set 等工廠函數來創建淺拷貝是更加 Pythonic 的。

複製任意 Python 對象

copy.copy() 和 copy.deepcopy() 函數可用於複製任意對象。以前面的列表複製示例為基礎。讓我們從定義一個簡單的 2D 點類開始:

class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x!r}, {self.y!r})'

__repr__() 函數使我們可以輕鬆地在 Python 解釋器中檢查從這個類創建的對象。

接下來,我們將創建一個 Point 實例,然後使用 copy 模塊複製(淺拷貝)它:

a = Point(23, 42)
b = copy.copy(a)
print(a is b)


False



圖解 Python 淺拷貝與深拷貝


a 和 b 分別指向了不同的 Point 實例。因為我們的 Point 對象使用不可變類型(int)作為其座標,所以在這種情況下,淺拷貝和深拷貝沒有區別。但我馬上會展開這個例子。

接下來定義另一個類來表示 2D 矩形。矩形將使用 Point 對象來表示它們的座標:

class Rectangle:
def __init__(self, topleft, bottomright):
self.topleft = topleft
self.bottomright = bottomright
def _repr__(self):
return (f'Rectangle({self.topleft!r}, {self.bottomright!r})')
# 創建一個 Rectangle 實例的淺拷貝
rect = Rectangle(Point(0, 1), Point(5, 6))
shallow_rect = copy.copy(rect)
print(rect)
print(shallow_rect)
print(rect is shallow_rect)


Rectangle(Point(0, 1), Point(5, 6))
Rectangle(Point(0, 1), Point(5, 6))
False



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


但是,因為我們只創建了原始列表的一個淺拷貝,所以 new_list 仍然包含對 lst 中存儲的原始子對象的引用。

也就是如上圖所示,lst 和 new_list 的子列表都指向了相同的對象。

子對象沒有被複制,它們只是在複製的列表中被再次引用。

因此,當你修改 lst 中的一個子對象時,這種修改也會反映到 new_list 中—— 這是因為兩個列表共享相同的子對象。這種複製只是一個淺的,一個層級的複製:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6], [7, 8, 9]]
[['x', 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


如果我們在第一步中創建了一個 lst 的深拷貝,那麼兩個對象就完全獨立了。這是對象的淺拷貝和深拷貝之間的實際區別。

使用 Python 標準庫中的 copy 模塊可以創建深拷貝,這個模塊為創建任意 Python 對象的淺拷貝和深拷貝提供了一個簡單的接口。

創建深拷貝

這次我們使用 deepcopy() 函數創建一個對象的深拷貝:

import copy
lst = [[1, 2, 3], [4, 5, 6]]
new_list = copy.deepcopy(lst)



圖解 Python 淺拷貝與深拷貝


從圖中可以看出 lst 和 new_list 中的子對象指向了不同的對象,如果對 lst 的子對象進行修改,將不會影響 new_list。

這一次,原始對象和複製對象都是完全獨立的。如前面所說,遞歸克隆了 lst,包括它的所有子對象:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


copy 模塊中的 copy.copy() 函數也可以創建對象的淺拷貝。使用 copy.copy() 可以明確地表示創建淺拷貝。對於內置集合,簡單地使用 list、dict 和 set 等工廠函數來創建淺拷貝是更加 Pythonic 的。

複製任意 Python 對象

copy.copy() 和 copy.deepcopy() 函數可用於複製任意對象。以前面的列表複製示例為基礎。讓我們從定義一個簡單的 2D 點類開始:

class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x!r}, {self.y!r})'

__repr__() 函數使我們可以輕鬆地在 Python 解釋器中檢查從這個類創建的對象。

接下來,我們將創建一個 Point 實例,然後使用 copy 模塊複製(淺拷貝)它:

a = Point(23, 42)
b = copy.copy(a)
print(a is b)


False



圖解 Python 淺拷貝與深拷貝


a 和 b 分別指向了不同的 Point 實例。因為我們的 Point 對象使用不可變類型(int)作為其座標,所以在這種情況下,淺拷貝和深拷貝沒有區別。但我馬上會展開這個例子。

接下來定義另一個類來表示 2D 矩形。矩形將使用 Point 對象來表示它們的座標:

class Rectangle:
def __init__(self, topleft, bottomright):
self.topleft = topleft
self.bottomright = bottomright
def _repr__(self):
return (f'Rectangle({self.topleft!r}, {self.bottomright!r})')
# 創建一個 Rectangle 實例的淺拷貝
rect = Rectangle(Point(0, 1), Point(5, 6))
shallow_rect = copy.copy(rect)
print(rect)
print(shallow_rect)
print(rect is shallow_rect)


Rectangle(Point(0, 1), Point(5, 6))
Rectangle(Point(0, 1), Point(5, 6))
False



圖解 Python 淺拷貝與深拷貝


跟前面 list 的例子一樣,rect 和 shallow_rect 的子對象都有相同的引用。在對象層級中修改一個對象,將看到這個變化也反映在淺拷貝的副本中:

rect.topleft.x = 999
print(rect)
print(shallow_rect)


Rectangle(Point(999, 1), Point(5, 6))
Rectangle(Point(999, 1), Point(5, 6))


接下來創建 Rectangle 的深拷貝並對其進行修改:

deep_rect = copy.deepcopy(rect)
deep_rect.topleft.x = 222
print(rect)
print(shallow_rect)
print(deep_rect)


Rectangle(Point(999, 1), Point(5, 6))
Rectangle(Point(999, 1), Point(5, 6))
Rectangle(Point(222, 1), Point(5, 6))



"
Python 中的賦值語句不會創建對象的拷貝,僅僅只是將名稱綁定至一個對象。對於不可變對象,通常沒什麼差別,但是處理可變對象或可變對象的集合時,你可能需要創建這些對象的 “真實拷貝”,也就是在修改創建的拷貝時不改變原始的對象。


本文將以圖文方式介紹 Python 中複製或“克隆”對象的操作。

首先介紹一下 Python 中淺拷貝與深拷貝的區別:

  • 淺拷貝:淺拷貝意味著構造一個新的集合對象,然後用原始對象中找到的子對象的引用來填充它。從本質上講,淺層的複製只有一層的深度。複製過程不會遞歸,因此不會創建子對象本身的副本。
  • 深拷貝:深拷貝使複製過程遞歸。這意味著首先構造一個新的集合對象,然後遞歸地用在原始對象中找到的子對象的副本填充它。以這種方式複製一個對象,遍歷整個對象樹,以創建原始對象及其所有子對象的完全獨立的克隆。


賦值與引用

在開始淺拷貝與深拷貝前,我們先來看一下 Python 中的賦值與引用。

lst = [1, 2, 3]
new_list = lst

從字面上看,上述語句創建了變量 lst 和 new_list,並且 lst 和 new_list 的賦值都為一個列表。但是,Python 的賦值語句並不會複製對象,而是會重新創建一個對象的引用。


圖解 Python 淺拷貝與深拷貝


可以看出,lst 和 new_list 都引用了同一個列表。

創建淺拷貝

不少教程裡都會提到,如果你有一個列表,當你想要修改列表中的值但卻不想影響原始對象時,可以使用 list 複製(淺拷貝)一個列表。

我們先來試一下:

lst = [1, 2, 3]
new_list = list(lst)


圖解 Python 淺拷貝與深拷貝


沒錯,lst 和 new_list 分別指向了不同的列表。當修改 lst 列表中的值時,並不會對 new_list 對象產生影響。

lst[0] = 'x'
print(lst)
print(new_list)


['x', 2, 3]
[1, 2, 3]



圖解 Python 淺拷貝與深拷貝


之所以說 list 語句是淺拷貝,是因為這種修改只對一層對象有效,當列表中有子對象時,對子對象的修改將影響原始對象和淺拷貝對象。

為了解釋這一說法,讓我們先創建一個嵌套列表,並使用 list 函數創建淺拷貝。

lst = [[1, 2, 3], [4, 5, 6]]
new_list = list(lst)

這裡 new_list 是有著和 lst 一樣內容的新的獨立的對象。


圖解 Python 淺拷貝與深拷貝


可以看到 lst 和 new_list 分別指向了不同的對象。

對第一層 lst 的修改,將不會對 new_list 副本造成影響。

lst.append([7, 8, 9])
print(lst)
print(new_list)


[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


但是,因為我們只創建了原始列表的一個淺拷貝,所以 new_list 仍然包含對 lst 中存儲的原始子對象的引用。

也就是如上圖所示,lst 和 new_list 的子列表都指向了相同的對象。

子對象沒有被複制,它們只是在複製的列表中被再次引用。

因此,當你修改 lst 中的一個子對象時,這種修改也會反映到 new_list 中—— 這是因為兩個列表共享相同的子對象。這種複製只是一個淺的,一個層級的複製:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6], [7, 8, 9]]
[['x', 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


如果我們在第一步中創建了一個 lst 的深拷貝,那麼兩個對象就完全獨立了。這是對象的淺拷貝和深拷貝之間的實際區別。

使用 Python 標準庫中的 copy 模塊可以創建深拷貝,這個模塊為創建任意 Python 對象的淺拷貝和深拷貝提供了一個簡單的接口。

創建深拷貝

這次我們使用 deepcopy() 函數創建一個對象的深拷貝:

import copy
lst = [[1, 2, 3], [4, 5, 6]]
new_list = copy.deepcopy(lst)



圖解 Python 淺拷貝與深拷貝


從圖中可以看出 lst 和 new_list 中的子對象指向了不同的對象,如果對 lst 的子對象進行修改,將不會影響 new_list。

這一次,原始對象和複製對象都是完全獨立的。如前面所說,遞歸克隆了 lst,包括它的所有子對象:

lst[0][0] = 'x'
print(lst)
print(new_list)


[['x', 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]



圖解 Python 淺拷貝與深拷貝


copy 模塊中的 copy.copy() 函數也可以創建對象的淺拷貝。使用 copy.copy() 可以明確地表示創建淺拷貝。對於內置集合,簡單地使用 list、dict 和 set 等工廠函數來創建淺拷貝是更加 Pythonic 的。

複製任意 Python 對象

copy.copy() 和 copy.deepcopy() 函數可用於複製任意對象。以前面的列表複製示例為基礎。讓我們從定義一個簡單的 2D 點類開始:

class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x!r}, {self.y!r})'

__repr__() 函數使我們可以輕鬆地在 Python 解釋器中檢查從這個類創建的對象。

接下來,我們將創建一個 Point 實例,然後使用 copy 模塊複製(淺拷貝)它:

a = Point(23, 42)
b = copy.copy(a)
print(a is b)


False



圖解 Python 淺拷貝與深拷貝


a 和 b 分別指向了不同的 Point 實例。因為我們的 Point 對象使用不可變類型(int)作為其座標,所以在這種情況下,淺拷貝和深拷貝沒有區別。但我馬上會展開這個例子。

接下來定義另一個類來表示 2D 矩形。矩形將使用 Point 對象來表示它們的座標:

class Rectangle:
def __init__(self, topleft, bottomright):
self.topleft = topleft
self.bottomright = bottomright
def _repr__(self):
return (f'Rectangle({self.topleft!r}, {self.bottomright!r})')
# 創建一個 Rectangle 實例的淺拷貝
rect = Rectangle(Point(0, 1), Point(5, 6))
shallow_rect = copy.copy(rect)
print(rect)
print(shallow_rect)
print(rect is shallow_rect)


Rectangle(Point(0, 1), Point(5, 6))
Rectangle(Point(0, 1), Point(5, 6))
False



圖解 Python 淺拷貝與深拷貝


跟前面 list 的例子一樣,rect 和 shallow_rect 的子對象都有相同的引用。在對象層級中修改一個對象,將看到這個變化也反映在淺拷貝的副本中:

rect.topleft.x = 999
print(rect)
print(shallow_rect)


Rectangle(Point(999, 1), Point(5, 6))
Rectangle(Point(999, 1), Point(5, 6))


接下來創建 Rectangle 的深拷貝並對其進行修改:

deep_rect = copy.deepcopy(rect)
deep_rect.topleft.x = 222
print(rect)
print(shallow_rect)
print(deep_rect)


Rectangle(Point(999, 1), Point(5, 6))
Rectangle(Point(999, 1), Point(5, 6))
Rectangle(Point(222, 1), Point(5, 6))



圖解 Python 淺拷貝與深拷貝


可以看出,深拷貝完全獨立於原始對象和淺拷貝對象。

參閱 copy 模塊文檔 可以對複製進行進一步的研究。例如,對象可以通過定義特殊的方法 __copy__() 和 __deepcopy__() 來控制如何複製它們。

謹記三件事

  • 創建對象的淺拷貝不會克隆子對象。因此,拷貝不會完全獨立於原始對象。
  • 一個對象的深拷貝會遞歸地克隆子對象。克隆對象完全獨立於原始對象,但是創建深拷貝速度較慢。
  • 可以使用 copy 模塊複製任意對象(包括自定義類)。
"

相關推薦

推薦中...