類淺複製和深複製的區別
類是定義物件屬性(資料)和行為(方法)的藍圖或模板。它是面向物件程式設計 (OOP) 的一個基本概念,它允許您根據類定義建立物件。
淺複製
淺複製建立一個新物件,儲存原始元素的引用。它不會複製巢狀物件,而是複製它們的引用。這意味著複製過程不會遞迴或建立巢狀物件的副本本身。淺複製比深複製快,但它比較“懶惰”,處理指標和引用。
它只是複製了指標的值,而不是建立指標指向的特定資訊的副本。因此,原始物件和副本都將具有指向相同底層資料的指標。
淺複製通常使用內建的 copy.copy() 方法或複製建構函式執行。
深複製
深複製建立一個新物件,儲存原始元素的副本。它與原始物件和副本不共享。深複製實際上克隆了底層資料。它與原始物件和副本不共享。深複製比淺複製慢,但它建立了物件及其所有子物件的完整副本。
可以使用 copy 模組提供的 **copy.deepcopy()** 方法實現深複製。
示例
在這個示例中,我們將建立一個類的例項並進行淺複製和深複製,以瞭解複製過程是如何工作的以及它如何影響內部物件的記憶體地址。
import copy class MyClass: def __init__(self, name, numbers): self.name = name self.numbers = numbers def __repr__(self): return f"MyClass(name='{self.name}', numbers={self.numbers})" # Creating an instance of MyClass original_obj = MyClass("Rahul Ravindranath", [53, 27, 82]) print("Memory address of original_obj.name:", id(original_obj.name)) print("Memory address of original_obj.numbers:", id(original_obj.numbers)) # Making a shallow copy shallow_copy = copy.copy(original_obj) # Checking memory addresses of internal objects for shallow copy print("Memory address of shallow_copy.name:", id(shallow_copy.name)) print("Memory address of shallow_copy.numbers:", id(shallow_copy.numbers)) # Creating a Deep copy deep_copy = copy.deepcopy(original_obj) # Checking memory addresses of internal objects for deep copy print("Memory address of deep_copy.name:", id(deep_copy.name)) print("Memory address of deep_copy.numbers:", id(deep_copy.numbers))
輸出
Memory address of original_obj.name: 23317216835824 Memory address of original_obj.numbers: 23317215777984 Memory address of shallow_copy.name: 23317216835824 Memory address of shallow_copy.numbers: 23317215777984 Memory address of deep_copy.name: 23317216835824 Memory address of deep_copy.numbers: 23317215706944
需要注意的是,不同裝置的記憶體地址會有所不同。
從上面的輸出中,我們可以推斷出 shallow_copy.name 和 shallow_copy.numbers 的記憶體地址與 original_obj 中相應屬性的記憶體地址相同。這表明內部物件沒有被複制,而是被引用。
當我們檢查 deep_copy.name 和 deep_copy.numbers 的記憶體地址時,我們發現它們與 original_obj 中相應屬性的記憶體地址不同。這表明內部物件已被複制,為 deep_copy 建立了單獨的例項。
示例
在此程式碼中,我們將建立一個類並進行淺複製和深複製,然後使用一些操作修改副本,並演示原始物件及其副本的變化。
演算法
定義一個名為 ClassEx 的類,其中包含一個 __init__ 方法,該方法使用名稱屬性和一個空列表屬性初始化例項。
實現 add_item 和 __str__ 方法,將專案追加到列表中,並提供例項的字串表示形式。
建立名為 original 的 ClassEx 例項
使用 add_item 方法將所需資料追加到原始物件及其副本中
顯示“original”例項以及淺複製和深複製
使用列表屬性和索引替換每個物件(包括原始物件、淺複製和深複製)中的某些專案。
列印更新後的原始物件、shallow_copy 和 deep_copy。
import copy class ClassEx: def __init__(self, name): self.name = name self.list = [] def add_item(self, item): self.list.append(item) def __str__(self): return f"{self.name}: {self.list}" # Create an instance of ClassEx original = ClassEx("Original") # Add some items to the list original.add_item("Item 1") original.add_item("Item 2") # Create a shallow copy of the object shallow_copy = copy.copy(original) # Add an item to the list of the shallow copy shallow_copy.add_item("Item 3") # Print the original object and the shallow copy print("Original object:", original) print("Shallow copy:", shallow_copy) # Create a deep copy of the object deep_copy = copy.deepcopy(original) # Add an item to the list of the deep copy deep_copy.add_item("Item 4") # Print the original object and the deep copy print("Original object:", original) print("Deep copy:", deep_copy) # Replace an item in the original object original.list[0] = "New Item 1" # Replace an item in the shallow copy shallow_copy.list[1] = "New Item 2" # Replace an item in the deep copy deep_copy.list[2] = "New Item 3" # Print the updated objects print("Original object:", original) print("Shallow copy:", shallow_copy) print("Deep copy:", deep_copy)
輸出
Original object: Original: ['Item 1', 'Item 2', 'Item 3'] Shallow copy: Original: ['Item 1', 'Item 2', 'Item 3'] Original object: Original: ['Item 1', 'Item 2', 'Item 3'] Deep copy: Original: ['Item 1', 'Item 2', 'Item 3', 'Item 4'] Original object: Original: ['New Item 1', 'New Item 2', 'Item 3'] Shallow copy: Original: ['New Item 1', 'New Item 2', 'Item 3'] Deep copy: Original: ['Item 1', 'Item 2', 'New Item 3', 'Item 4']
淺複製與原始物件共享內部物件,而深複製建立內部物件的獨立副本。對淺複製和原始物件所做的更改會相互影響,而深複製是完全獨立的,當在深複製中進行修改時不會影響原始物件。
主要區別
淺複製 | 深複製 | |
---|---|---|
記憶體共享 | 與原始物件共享記憶體位置 | 建立具有獨立記憶體位置的獨立副本 |
效能 | 更快、更高效,尤其是在大型物件或複雜資料結構中 | 較慢,可能消耗更多記憶體,尤其是在大型物件或深度巢狀中 |
資料完整性 | 可能導致意外修改原始物件 | 透過隔離複製的物件來確保資料完整性 |
對複製物件的更改 | 修改可能會影響原始物件,反之亦然 | 修改不會影響原始物件 |
依賴關係和引用 | 共享引用可能導致意外副作用或資料完整性問題 | 透過複製所有巢狀物件來處理迴圈引用和複雜的相互依賴關係 |
結論
淺複製用於建立物件的當前狀態的備份或快照。當實現寫時複製行為(僅在對複製的物件進行更改時才進行復制)以及基於現有物件建立具有初始值的新物件時,它更受青睞。
深複製用於當我們想要建立物件及其巢狀物件的完全獨立副本時。它有助於物件的序列化和反序列化,其中複製的物件需要獨立儲存或傳輸。