自学内容网 自学内容网

Python 的深拷贝和浅拷贝有什么区别?

在Python中,深拷贝(deep copy)和浅拷贝(shallow copy)是两种复制对象的方式,它们的主要区别在于如何处理对象的子对象。

浅拷贝(Shallow Copy)

浅拷贝创建一个新的对象,但不会递归地复制原对象中的子对象,而是复制子对象的引用。这意味着,如果原对象中的子对象发生变化,浅拷贝的对象中的子对象也会随之变化。

import copy

# 原始列表
original_list = [1, 2, [3, 4]]

# 浅拷贝
shallow_copied_list = copy.copy(original_list)

# 修改原始列表中的子列表
original_list[2][0] = 'X'

print("Original list:", original_list)  # Output: [1, 2, ['X', 4]]
print("Shallow copied list:", shallow_copied_list)  # Output: [1, 2, ['X', 4]]
深拷贝(Deep Copy)

深拷贝创建一个新的对象,并递归地复制原对象中的所有子对象。这意味着,即使原对象中的子对象发生变化,深拷贝的对象中的子对象也不会随之变化。

import copy

# 原始列表
original_list = [1, 2, [3, 4]]

# 深拷贝
deep_copied_list = copy.deepcopy(original_list)

# 修改原始列表中的子列表
original_list[2][0] = 'X'

print("Original list:", original_list)  # Output: [1, 2, ['X', 4]]
print("Deep copied list:", deep_copied_list)  # Output: [1, 2, [3, 4]]

使用建议

1. 使用浅拷贝的场景
  • 当你只需要复制顶层对象,而不关心子对象的变化时:例如,当你有一个包含不可变对象(如整数、字符串)的列表,并且你希望创建一个新的列表来存储这些不可变对象时。
import copy

# 原始列表
original_list = [1, 2, 3]

# 浅拷贝
shallow_copied_list = copy.copy(original_list)

# 修改原始列表
original_list.append(4)

print("Original list:", original_list)  # Output: [1, 2, 3, 4]
print("Shallow copied list:", shallow_copied_list)  # Output: [1, 2, 3]
2. 使用深拷贝的场景
  • 当你需要完全独立的副本,包括所有子对象时:例如,当你有一个包含可变对象(如列表、字典)的复杂数据结构,并且你希望创建一个新的数据结构来存储这些可变对象的独立副本时。
import copy

# 原始数据结构
original_data = {
    'a': 1,
    'b': [2, 3],
    'c': {'d': 4}
}

# 深拷贝
deep_copied_data = copy.deepcopy(original_data)

# 修改原始数据结构中的子对象
original_data['b'][0] = 'X'
original_data['c']['d'] = 'Y'

print("Original data:", original_data)  # Output: {'a': 1, 'b': ['X', 3], 'c': {'d': 'Y'}}
print("Deep copied data:", deep_copied_data)  # Output: {'a': 1, 'b': [2, 3], 'c': {'d': 4}}

注意事项

1. 性能考虑
  • 深拷贝的性能开销较大:因为深拷贝需要递归地复制所有子对象,所以对于大型数据结构,深拷贝可能会非常耗时。在这种情况下,可以考虑使用其他方法来避免深拷贝,例如使用不可变数据结构或手动复制必要的部分。
import copy
import time

# 创建一个大型列表
large_list = [list(range(1000)) for _ in range(1000)]

# 浅拷贝
start_time = time.time()
shallow_copied_list = copy.copy(large_list)
end_time = time.time()
print("Shallow copy time:", end_time - start_time)  # Output: 非常快

# 深拷贝
start_time = time.time()
deep_copied_list = copy.deepcopy(large_list)
end_time = time.time()
print("Deep copy time:", end_time - start_time)  # Output: 较慢
2. 循环引用
  • 深拷贝处理循环引用时可能会导致问题:如果对象中存在循环引用(即对象的某个子对象引用了对象本身或其祖先对象),深拷贝可能会陷入无限递归,导致栈溢出。copy.deepcopy函数可以处理循环引用,但会增加额外的开销。
import copy

# 创建一个包含循环引用的对象
a = []
b = [a]
a.append(b)

# 深拷贝
deep_copied_a = copy.deepcopy(a)

print(deep_copied_a)  # Output: [[...]]
3. 自定义对象的拷贝
  • 自定义对象需要实现__copy____deepcopy__方法:如果你有一个自定义类,并且希望控制其拷贝行为,可以实现__copy____deepcopy__方法。
import copy

class MyClass:
    def __init__(self, value):
        self.value = value
        self.child = None

    def __copy__(self):
        new_instance = MyClass(self.value)
        new_instance.child = self.child  # 浅拷贝子对象
        return new_instance

    def __deepcopy__(self, memo):
        new_instance = MyClass(copy.deepcopy(self.value, memo))
        new_instance.child = copy.deepcopy(self.child, memo)  # 深拷贝子对象
        return new_instance

# 创建一个自定义对象
original = MyClass(1)
original.child = MyClass(2)

# 浅拷贝
shallow_copied = copy.copy(original)

# 深拷贝
deep_copied = copy.deepcopy(original)

print(shallow_copied.value, shallow_copied.child.value)  # Output: 1 2
print(deep_copied.value, deep_copied.child.value)  # Output: 1 2
  • 浅拷贝适用于只需要复制顶层对象的场景,性能较好,但需要注意子对象的变化会影响拷贝对象。
  • 深拷贝适用于需要完全独立副本的场景,但性能开销较大,需要注意处理循环引用和自定义对象的拷贝行为。

原文地址:https://blog.csdn.net/liangzai215/article/details/144705441

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!