Python中级之深浅拷贝

发布时间 2023-12-06 19:47:21作者: Lea4ning

深浅拷贝

Python源码对深浅拷贝的解释

  • 以下来源于Python源码中对copy的解释
# 英文原文
The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances).

- A shallow copy constructs a new compound object and then (to the
  extent possible) inserts *the same objects* into it that the
  original contains.

- A deep copy constructs a new compound object and then, recursively,
  inserts *copies* into it of the objects found in the original.

Two problems often exist with deep copy operations that don't exist
with shallow copy operations:

 a) recursive objects (compound objects that, directly or indirectly,
    contain a reference to themselves) may cause a recursive loop

 b) because deep copy copies *everything* it may copy too much, e.g.
    administrative data structures that should be shared even between
    copies

Python's deep copy operation avoids these problems by:

 a) keeping a table of objects already copied during the current
    copying pass

 b) letting user-defined classes override the copying operation or the
    set of components copied

This version does not copy types like module, class, function, method,
nor stack trace, stack frame, nor file, socket, window, nor any
similar types.
# 中文翻译
浅拷贝和深拷贝的区别仅在于复合对象(包含其他对象的对象,如列表或类实例)方面。

- 浅拷贝构建一个新的复合对象,然后(在可能的范围内)将*与原对象相同的对象*插入其中。
- 深拷贝构建一个新的复合对象,然后递归地插入其中原始对象的*副本*。

深拷贝操作通常存在两个问题,而浅拷贝操作则不存在:

a) 递归对象(直接或间接地包含对自身引用的复合对象)可能导致递归循环

b) 因为深拷贝会复制*所有内容*,可能复制过多,例如,应该在拷贝之间共享的管理数据结构

Python 的深拷贝操作通过以下方式避免这些问题:

a) 在当前拷贝过程中保持一个已复制对象的表

b) 允许用户定义的类覆盖拷贝操作或要复制的组件集

这个版本不会复制诸如模块、类、函数、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口等类型。

代码解释

import copy
# 浅拷贝 外层嵌套
copy_old = [1, 2, [3, 4]]
copy_new = copy.copy(copy_old)
copy_old.append(5)
print(copy_new, id(copy_new))   # [1, 2, [3, 4]] 2557819770432      # 浅拷贝的对象
print(copy_old, id(copy_old))   # [1, 2, [3, 4], 5] 2557819770176   # 被复制的对象

# 浅拷贝 嵌套中的可迭代对象
copy_old = [1, 2, [3, 4]]
copy_new = copy.copy(copy_old)
copy_old[2].append(5)
print(copy_new, id(copy_new))   # [1, 2, [3, 4, 5]] 2406245488192   # 可迭代对象浅拷贝的对象
print(copy_old, id(copy_old))   # [1, 2, [3, 4, 5]] 2406245487936   # 被复制的对象

print('浅拷贝与深拷贝的区别'.center(20,'>'))

# 深拷贝
copy_old = [1, 2, [3, 4]]
copy_new = copy.deepcopy(copy_old)
copy_old.append(5)
copy_old[2].append(5)
print(copy_new, id(copy_new))   # [1, 2, [3, 4]] 2259169924672
print(copy_old, id(copy_old))   # [1, 2, [3, 4, 5], 5] 2259169924416
# 深拷贝不管使修改外层列表还是嵌套列表,拷贝过的内容都不会有所改变