类浅拷贝和深拷贝的区别


类是定义对象属性(数据)和行为(方法)的蓝图或模板。它是面向对象编程 (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']

浅拷贝与原始对象共享内部对象,而深拷贝创建内部对象的独立副本。对浅拷贝和原始对象所做的更改会相互影响,而深拷贝是完全独立的,当在深拷贝中进行修改时不会影响原始对象。

主要区别

浅拷贝 深拷贝
内存共享 与原始对象共享内存位置 创建具有独立内存位置的独立副本
性能 更快、更高效,尤其是在大型对象或复杂数据结构中 较慢,可能消耗更多内存,尤其是在大型对象或深度嵌套中
数据完整性 可能导致意外修改原始对象 通过隔离复制的对象来确保数据完整性
对复制对象的更改 修改可能会影响原始对象,反之亦然 修改不会影响原始对象
依赖关系和引用 共享引用可能导致意外副作用或数据完整性问题 通过复制所有嵌套对象来处理循环引用和复杂的相互依赖关系

结论

浅拷贝用于创建对象的当前状态的备份或快照。当实现写时复制行为(仅在对复制的对象进行更改时才进行复制)以及基于现有对象创建具有初始值的新对象时,它更受青睐。

深拷贝用于当我们想要创建对象及其嵌套对象的完全独立副本时。它有助于对象的序列化和反序列化,其中复制的对象需要独立存储或传输。

更新于: 2023年8月10日

524 次浏览

开启你的 职业生涯

通过完成课程获得认证

立即开始
广告