基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Python 中深拷贝(Deep Copy)和浅拷贝(Shallow Copy)的区别?

知识点图片

在 Python 中,深拷贝(Deep Copy)浅拷贝(Shallow Copy)的主要区别在于如何处理对象内部的子对象(nested objects)

简单来说:

  • 浅拷贝:只复制最外层的容器,内部的元素依然是引用(指向原来的对象)。
  • 深拷贝:不仅复制最外层的容器,还递归地复制内部所有的元素,完全独立。

为了讲清楚,我们需要先引入一个基准概念:直接赋值


0. 预备知识:直接赋值 (=)

直接赋值不是拷贝。它只是给同一个对象起了一个别名。

  • 现象b = a
  • 结果ab 指向内存中完全相同的地址。修改 b 也就是修改 a

1. 浅拷贝 (Shallow Copy)

浅拷贝会创建一个新的对象(容器),但是这个新对象里的元素,依然是指向原对象中元素的引用

  • 实现方式
    • copy.copy(obj)
    • 列表切片 list[:]
    • 工厂函数 list(), dict()
    • 对象自带的 .copy() 方法
  • 特点
    • 第一层是独立的:如果你修改最外层的数据(例如增加/删除元素),原对象不会受影响。
    • 内部嵌套层是共享的:如果你修改内部嵌套的可变对象(例如列表里的列表),原对象受影响。

代码示例:

python
import copy

# 原列表:包含一个整数和一个子列表
a = [1, [2, 3]]

# 浅拷贝
b = copy.copy(a) 
# 或者 b = a[:] 
# 或者 b = a.copy()

# 1. 修改最外层元素(安全)
b.append(4)
print(a) # [1, [2, 3]]    <- 原列表没变
print(b) # [1, [2, 3], 4] <- 新列表变了

# 2. 修改内部嵌套列表(危险!会影响原对象)
b[1][0] = 999
print(a) # [1, [999, 3]]  <- 原列表也被改了!
print(b) # [1, [999, 3], 4]

2. 深拷贝 (Deep Copy)

深拷贝会创建一个新的对象,并且递归地将原对象中的所有元素(包括子元素、子元素的子元素...)都复制一份。

  • 实现方式
    • copy.deepcopy(obj)
  • 特点
    • 新对象和原对象在内存中是完全独立的。
    • 无论怎么修改新对象(哪怕是修改最深层的嵌套数据),原对象都不会受影响。
    • 缺点:速度比浅拷贝慢,且占用更多内存。

代码示例:

python
import copy

# 原列表
a = [1, [2, 3]]

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

# 1. 修改最外层(安全)
b.append(4)

# 2. 修改内部嵌套列表(安全!原对象不受影响)
b[1][0] = 999

print(a) # [1, [2, 3]]       <- 原列表完全没变,保持原样
print(b) # [1, [999, 3], 4]  <- 只有新列表变了

3. 总结对比表

特性 直接赋值 (=) 浅拷贝 (copy.copy) 深拷贝 (copy.deepcopy)
新对象创建 否 (只是别名) 是 (仅外壳) 是 (完全的新个体)
第一层元素 共享 独立 独立
嵌套子元素 共享 共享 (指向同一内存) 独立 (递归复制)
速度 最快 较慢
内存占用 最小 中等 最大

4. 特殊情况:不可变对象 (Immutable Objects)

对于不可变对象(如 int, str, tuple),Python 会进行优化。

  • 如果元组里只包含不可变对象(例如 (1, 2)),copydeepcopy 通常不会创建新对象,而是直接返回原对象的引用(因为反正你也改不了它,复制没有意义)。
  • 但如果元组里包含可变对象(例如 (1, [2, 3])),deepcopy 依然会递归复制那个列表。

一句话概括

  • 浅拷贝:藕断丝连(外壳换了,里面还连着)。
  • 深拷贝:彻底分手(完全独立,互不相干)。
00:00
00:00