Python 的赋值为什么不会复制对象?拆开引用、浅拷贝与深拷贝

简介: list 能装下任何类型,是因为它存的是 PyObject* 指针数组:类型信息挂在对象自己头上。代价是每元素 8 字节指针加完整对象头——实测 100 万个整数,list 总内存约 34.3MB,是 array 的 9 倍。本文用 sys.getsizeof 一格格量给你看,并给出什么时候该换 array/numpy 的判断标准

先看一段让新手崩溃的代码:

a = [1, 2, 3]
b = a          # 只是赋值,没有复制
b.append(4)
print(a)       # [1, 2, 3, 4]  —— a 居然也变了

b = a 一行都没"改错",a 却被牵连了。要解释这件事,得回到上一期讲过的那个事实:Python 的变量不是盒子,是标签。

一、赋值的真相:复制的是指针,不是对象

CPython 里每个变量名都只是指向某个 PyObject* 的引用。b = a 做的事只有一件:把 a 指向的那个指针抄给 b,再调用一次 Py_INCREF 把引用计数加一。对象本身一个字节都没动。

在解释器里验证:

>>> id(a) == id(b)
True
>>> sys.getrefcount(a)
3    # a、b,加上传参临时持有的一次

id() 相同,说明 a 和 b 是同一个对象的两个名字。所谓"赋值",本质上就是把 8 字节的指针抄了一遍——这也解释了为什么 Python 里赋值快得不像话。

所以开头那段代码不是 bug:b.append(4) 操作的是那个唯一的列表对象,a 和 b 都指着它,当然一起变。

二、浅拷贝:只复制最外层

想拿到独立副本,最直接的是浅拷贝:

c = a.copy()   # 等价于 a[:] 和 list(a)

浅拷贝会新建一个列表对象,把外层的指针数组逐个抄一遍——注意抄的还是指针。于是:

inner = [9]
outer = [inner]
sh = outer.copy()
sh[0].append(8)
print(outer[0])          # [9, 8] —— 内层被共享了
print(outer is sh)       # False,外层确实是新对象
print(outer[0] is sh[0]) # True,内层还是同一个

实测一组数据(CPython 3.13):2 万行嵌套列表占 9.3MB,整体浅拷贝之后内存只增加 0.16MB——增加的正是 2 万个指针槽(20,000 × 8 字节 ≈ 156KB),所有内层对象原封不动地共享。

浅拷贝的真正含义:外层新,内层旧。

三、深拷贝:递归到底的代价

要连内层一起复制,就得用 copy.deepcopy,它会沿着引用一路递归下去,把整棵对象树复制一遍。代价是惊人的:

lst = [{
   'k': [i]*10} for i in range(2000)]
%timeit lst.copy()          # 约 0.010ms
%timeit copy.deepcopy(lst)  # 约 17.2ms

同样 2000 个元素,深拷贝比浅拷贝慢了大约 1700 倍。原因很直白:浅拷贝是 memcpy 级别的指针搬运,深拷贝要对每个嵌套对象做递归遍历、逐个新建、维护"已复制"备忘录(memo 字典,用来正确处理循环引用和共享子对象)。

顺带说一个高频面试点:deepcopy 之所以能处理 x.append(x) 这种自引用结构,靠的就是 memo——复制前先查"这个对象是不是已经复制过了"。

四、函数传参也一样:传的是引用

def fill(lst):
    lst.append(1)

data = []
fill(data)
print(data)   # [1] —— 出了函数还在

Python 的参数传递常被叫做"传对象引用":形参和实参是同一个对象的两个名字。想避免函数污染外部数据,入口处先 data = data.copy()。

五、一个判断口诀

最后给一个实用口诀,按需选拷贝深度:

  • 元素是不可变类型(数字、字符串、元组):浅拷贝就够,反正它们改不了;
  • 一层嵌套、只改外层:浅拷贝;
  • 嵌套可变对象、各层都要独立:深拷贝,但先掂量那 1700 倍的性能差;
  • 只是想传个名字:直接赋值,零成本。

记住核心机制就够了:Python 里 "=" 永远只复制指针。 复制对象的任何承诺,都来自 copy 模块,而不是赋值运算符本身。

(实测环境:CPython 3.13,Windows;代码可直接粘贴复现)

相关文章
|
4天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
|
云安全 安全 网络安全
|
5天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
861 1
|
17天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
2971 49
|
11天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
2100 2
|
5天前
|
安全 算法 定位技术
《高性价比人生指南》完整原版:普通人用最少的资源,过好这一生的底层逻辑~How To Live Better
📖《高性价比人生指南》是一份基于实证、拒绝焦虑的生存手册,倡导以“人生时薪”为视角,重新计算时间、金钱与精力的成本与收益。它不承诺逆袭,只教人算清账:省下的钱若耗掉时间便亏;买体验比买物品更值;睡眠是最高杠杆的健康投资;关系贵在情绪价值而非表面热络;学习重在改变行为而非自我安慰。核心理念:用低成本、高回报的微小行动,换取长期的选择权——不是成为谁,而是掌控自己人生的主动权。
|
10天前
|
人工智能 JSON Linux
【保姆级】ComfyUI部署教程(下载+安装+配置+工作流,2026最新)
ComfyUI 是一款开源节点式AI生成工具,支持图像、视频、音频及3D内容创作。通过拖拽连线组合模型加载、提示词、采样等节点,构建可复用、易修改的工作流,兼容SD1.5、SDXL、Flux、Qwen Image等主流模型。
|
4天前
|
Linux 开发工具 iOS开发
Codex保姆级教程(下载+安装+登录+使用,含所有版本,2026最新)
Codex是OpenAI推出的开源AI编程智能体,本地运行,可理解整个代码库,支持自然语言指令改代码、执行命令、跑测试、修Bug,兼容Win/macOS/Linux。(239字)