Python 深浅拷贝

Python 深浅拷贝详解

什么是深浅拷贝?

在 Python 中,对象赋值、浅拷贝和深拷贝是常见的操作,它们在复制对象时有着不同的行为。

  • 赋值(直接赋值): 只是创建了一个新的变量名,但这个变量名指向了原有的对象。也就是说,两个变量名指向的是同一个内存地址。
  • 浅拷贝: 创建一个新的对象,这个新对象包含了原对象中所有元素的引用。对于不可变对象(如数字、字符串),引用和复制是等价的。但对于可变对象(如列表、字典),新对象中的元素仍然指向原对象中的元素。
  • 深拷贝: 创建一个新的对象,并且递归地复制原对象中的所有元素。这意味着新对象和原对象是完全独立的,修改一个对象不会影响另一个对象。

为什么要区分深浅拷贝?

  • 避免意外修改: 当多个变量指向同一个可变对象时,修改其中一个变量会影响其他变量。深拷贝可以避免这种问题。
  • 传递参数: 在函数中传递参数时,如果不想修改原对象,可以使用深拷贝。
  • 数据结构: 在处理复杂数据结构时,深拷贝可以确保每个子对象都是独立的。

如何实现深浅拷贝?

浅拷贝:

  • copy.copy() 方法:

    1
    2
    3
    4
    import copy
    list1 = [1, [2, 3]]
    list2 = copy.copy(list1)
    # list2 和 list1 的第一层元素是独立的,但第二层列表仍然是同一个
  • 切片操作:

    1
    2
    list1 = [1, 2, 3]
    list2 = list1[:]

深拷贝:

  • copy.deepcopy() 方法:

    1
    2
    3
    4
    import copy
    list1 = [1, [2, 3]]
    list2 = copy.deepcopy(list1)
    # list2 和 list1 完全独立

深浅拷贝示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import copy

# 浅拷贝
list1 = [1, [2, 3], 4]
list2 = copy.copy(list1)
list2[0] = 100
list2[1][0] = 200
print(list1) # 输出:[1, [200, 3], 4]
print(list2) # 输出:[100, [200, 3], 4]

# 深拷贝
list1 = [1, [2, 3], 4]
list2 = copy.deepcopy(list1)
list2[0] = 100
list2[1][0] = 200
print(list1) # 输出:[1, [2, 3], 4]
print(list2) # 输出:[100, [200, 3], 4]

总结

  • 浅拷贝 只复制对象的顶层结构,对于嵌套的可变对象,其引用仍然指向原对象。
  • 深拷贝 递归地复制整个对象,创建一个完全独立的新对象。
  • 选择哪种拷贝方式取决于具体的需求。如果需要修改副本而不影响原对象,则使用深拷贝;如果只修改顶层结构,则可以使用浅拷贝。

常见问题

  • 什么时候需要深拷贝?
    • 当你希望复制一个对象,并且在修改副本时不影响原对象时。
    • 当你处理复杂的数据结构,需要确保每个子对象都是独立的时。
  • 深拷贝的性能开销如何?
    • 深拷贝比浅拷贝的开销更大,尤其是对于大型复杂的对象。因此,在性能要求较高的场景下,需要谨慎使用深拷贝。

拓展

  • 自定义对象的深拷贝: 对于自定义的类,可以通过实现 __deepcopy__ 方法来定制深拷贝行为。
  • pickle 模块: 可以将 Python 对象序列化为字节流,然后反序列化为新的对象,实现深拷贝。

Python 深浅拷贝
https://chrrr1y.github.io/2024/08/14/Python深浅拷贝/
作者
Chrrr1y
发布于
2024年8月14日
更新于
2024年8月15日
许可协议