类浅拷贝和深拷贝的区别
类是定义对象属性(数据)和行为(方法)的蓝图或模板。它是面向对象编程 (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']
浅拷贝与原始对象共享内部对象,而深拷贝创建内部对象的独立副本。对浅拷贝和原始对象所做的更改会相互影响,而深拷贝是完全独立的,当在深拷贝中进行修改时不会影响原始对象。
主要区别
浅拷贝 | 深拷贝 | |
---|---|---|
内存共享 | 与原始对象共享内存位置 | 创建具有独立内存位置的独立副本 |
性能 | 更快、更高效,尤其是在大型对象或复杂数据结构中 | 较慢,可能消耗更多内存,尤其是在大型对象或深度嵌套中 |
数据完整性 | 可能导致意外修改原始对象 | 通过隔离复制的对象来确保数据完整性 |
对复制对象的更改 | 修改可能会影响原始对象,反之亦然 | 修改不会影响原始对象 |
依赖关系和引用 | 共享引用可能导致意外副作用或数据完整性问题 | 通过复制所有嵌套对象来处理循环引用和复杂的相互依赖关系 |
结论
浅拷贝用于创建对象的当前状态的备份或快照。当实现写时复制行为(仅在对复制的对象进行更改时才进行复制)以及基于现有对象创建具有初始值的新对象时,它更受青睐。
深拷贝用于当我们想要创建对象及其嵌套对象的完全独立副本时。它有助于对象的序列化和反序列化,其中复制的对象需要独立存储或传输。