Python中赋值、浅拷贝与深拷贝的区别是什么?

林见深
林见深
发布时间:2026-10-24| 6人浏览过
原创
在 Python 中,赋值、浅拷贝与深拷贝的核心差异在于对内存地址的引用方式以及对嵌套层级对象的复制深度。简单来说:直接赋值(=)仅创建对象的引用别名,不产生任何新对象;浅拷贝(如 copy.copy() 或切片)会创建一个全新的外层容器对象,但内部引用的子对象仍与原对象共享;深拷贝(copy.deepcopy())则会递归遍历并复制容器及其内部所有层级的可变子对象,生成一份完全独立的物理副本。

一、Python 的变量模型:理解引用的基石

要彻底区分这三种操作,首先需要理解 Python 的变量绑定机制。在 Python 中,“一切皆对象”,变量本质上并不是存储具体数据的“盒子”,而是一个指向内存中对象的“指针标签”。

当执行 x = [1, 2] 时,系统在堆内存中创建了列表对象 [1, 2],并将变量名 x 绑定到该对象的内存地址。内置函数 id() 可以获取对象的唯一内存标识符,而操作符 is 用于判断两个变量是否指向同一个内存地址。

Python中赋值、浅拷贝与深拷贝的区别是什么?
图 1:赋值、浅拷贝与深拷贝在内存中的底层引用结构对比

二、直接赋值(=):别名绑定的行为分析

在 Python 中,使用等号 = 并不是复制数据,而是为已有对象赋予一个新的变量别名。两个变量名在内部指向完全一致的内存物理地址。

# 赋值示例
origin = [1, [2, 3]]
alias = origin

print("origin id:", id(origin))
print("alias id: ", id(alias))
print("两者是否指向同一对象:", origin is alias)  # 输出: True

# 无论修改外层还是内层,两者都会同步改变
origin[0] = 99
origin[1].append(4)

print("alias 的内容:", alias)  # 输出: [99, [2, 3, 4]]

这种特性的主要用途是提高变量传递的效率。在函数调用时,Python 的参数传递机制采用“对象的引用传递”(Pass by Object Reference),其本质就是赋值操作。如果函数内部直接修改了传入的可变对象,函数外部的原始数据也会随之被篡改。

三、浅拷贝(Shallow Copy):顶层复制与子对象共享

浅拷贝会构造一个新的容器对象,然后将原对象中的所有顶层元素引用逐个插入到新容器中。如果元素是基本不可变类型(如整型、字符串),修改外层元素不会相互干扰;但如果元素本身是嵌套的可变容器(如子列表、子字典),新旧容器中存储的子对象引用依然指向同一个内存块。

常见的浅拷贝实现方式

  • 使用标准库内置函数:copy.copy(x)
  • 列表切片操作:new_list = old_list[:]
  • 容器内置方法:new_list = old_list.copy() 或 new_dict = old_dict.copy()
  • 类构造函数/工厂函数:new_list = list(old_list)、new_dict = dict(old_dict)
import copy

# 浅拷贝示例
origin = [10, [20, 30]]
shallow = copy.copy(origin)

print("外层对象是否相同:", origin is shallow)          # 输出: False (生成了新外层容器)
print("嵌套子列表是否相同:", origin[1] is shallow[1])  # 输出: True  (共享内部子列表)

# 1. 修改原对象的顶层不可变元素
origin[0] = 99
print("shallow 外层不受影响:", shallow)  # 输出: [10, [20, 30]]

# 2. 修改原对象的内部嵌套可变列表
origin[1].append(999)
print("shallow 内层被同步修改:", shallow)  # 输出: [10, [20, 30, 999]]

为了直观观察修改嵌套对象时的传播过程,下方的状态演变图展示了在调用 append 后,各变量的实际变化。

Python中赋值、浅拷贝与深拷贝的区别是什么?
图 2:修改嵌套可变对象后三种拷贝模式的状态表现差异

四、深拷贝(Deep Copy):全层级递归隔离

深拷贝(Deep Copy)会构建一个全新容器,并递归复制原对象内部涉及的所有子对象。只有当遇到不可变元素(如整数、浮点数、纯字符串、仅包含不可变元素的元组)时,为了节省内存,Python 会复用该不可变对象的引用;对于所有可变结构,都会在内存中重建一套完全平行的对象网络。

深拷贝必须通过标准库中的 copy.deepcopy() 实现:

import copy

origin_tree = {
    "name": "工程节点",
    "params": [100, 200],
    "children": [{"sub_id": 1}]
}

deep_clone = copy.deepcopy(origin_tree)

# 验证所有层级的独立性
print("外层字典独立:", origin_tree is deep_clone)                      # False
print("params 列表独立:", origin_tree["params"] is deep_clone["params"])  # False
print("子字典独立:    ", origin_tree["children"][0] is deep_clone["children"][0])  # False

# 即使修改深层嵌套字典,原对象也丝毫不受干扰
deep_clone["children"][0]["sub_id"] = 999
print("原字典保持不变:", origin_tree["children"][0]["sub_id"])  # 输出: 1
深拷贝内部机制——解决循环引用: 如果一个数据结构存在自引用(例如列表包含自身 a.append(a)),普通递归复制会陷入无限死循环。copy.deepcopy() 在内部维护了一个名为 memo 的字典,用于记录已经复制过的对象映射关系({id(origin): cloned_obj})。一旦检测到当前对象已在 memo 中,便直接返回已有副本,从而避免死循环。

五、开发中如何选择:决策流程图

在工程开发中,盲目使用 deepcopy 会导致明显的性能下降和内存飙升。开发者应当根据数据的嵌套深度与修改需求,选择最合理的方案。

Python中赋值、浅拷贝与深拷贝的区别是什么?
图 3:针对不同数据结构与业务场景的拷贝方案决策路径

六、核心差异全景对比与工程避坑指南

为了便于查阅和快速选型,下面对三种机制的各项核心技术指标进行汇总:

对比维度 直接赋值 ( = ) 浅拷贝 (Shallow Copy) 深拷贝 (Deep Copy)
外层容器地址 完全相同 (a is b 为 True) 全新对象 (a is b 为 False) 全新对象 (a is b 为 False)
嵌套可变子对象 完全相同 完全相同 (共享引用) 递归克隆 (生成新对象)
修改顶层元素 相互影响 互不影响 互不影响
修改嵌套子元素 相互影响 相互影响 互不影响
常用语法 b = a copy.copy(a)
a[:] / a.copy()
copy.deepcopy(a)
内存与执行开销 极小(无内存复制) 较小(仅复制第一层引用) 较大(遍历对象图,深层分配)
Python中赋值、浅拷贝与深拷贝的区别是什么?
图 4:赋值、浅拷贝与深拷贝的关键维度特征与避坑清单

常见典型陷阱解析

陷阱 1:列表乘法创建嵌套列表导致的共享引用

很多开发者初学时会使用 matrix = [[0] * 3] * 3 初始化二维列表。这里的外层乘法本质上是在执行浅拷贝引用,导致外层列表的 3 个元素其实指向了同一个子列表。执行 matrix[0][0] = 1 会导致三行同时被更改。正确做法是使用列表推导式:matrix = [[0] * 3 for _ in range(3)],保证每次循环都创建独立的子列表实例。

陷阱 2:不可变对象的浅拷贝优化

对于不可变类型(如 tuple、str、int),执行 copy.copy(t) 并不会创建新对象,而是直接返回原对象的引用,因为不可变对象不可篡改,复用引用完全安全。但若元组中包含了可变列表(例如 t = ([], )),若要使其内部列表完全独立,仍需使用 copy.deepcopy(t)。

总结

掌握赋值、浅拷贝与深拷贝的核心在于把握对象的层级边界:

  • 需要变量共享同一种状态,仅作引用传递时,使用直接赋值;
  • 处理扁平结构、单层列表字典,或仅需修改顶层容器时,使用浅拷贝以兼顾性能与安全;
  • 涉及树形配置、复杂嵌套字典或需要彻底隔离历史快照时,使用深拷贝确保不受下游修改干扰。
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。