Python 到底是值传递还是引用传递?一个赋值实验讲透,别再背结论了

简介: Python 既不是值传递也不是引用传递,而是传对象引用。本文用一个赋值实验讲透:函数收到的不是实参副本也不是实参本身,而是同一个对象的引用;并澄清 mutable 与 immutable、默认参数记仇、+= 不总是等于 + 三个经典陷阱。

结论先行:Python 既不是值传递,也不是引用传递,而是"传对象引用"(pass by object reference)。函数收到的不是实参的副本,也不是实参本身,而是同一个对象的引用——效果上类似"引用的值传递"。所以可变类型(list、dict)在函数里改内容,外面看得见;不可变类型(int、str、tuple)在函数里"改"变量,外面看不见。把这个结论背下来没用,看完下面这个实验,你一辈子忘不了。


1. 一个实验:先说反直觉的现象

def add_one(x):
    x = x + 1          # 对数字"加一"

def append_one(lst):
    lst.append(1)      # 往列表里塞一个元素

a = 10
add_one(a)
print(a)               # 10!没变

b = [1, 2]
append_one(b)
print(b)               # [1, 2, 1]!变了

同样是把参数传进函数,a 纹丝不动,b 却被改了。如果 Python 是"值传递",b 不该变;如果是"引用传递",a 也该跟着变。两个都不符合——所以这个问题才吵了这么多年。

别急,先记住这个现象:变的是 list,不变的是 int。规律就藏在类型里。

2. 本质:Python 的变量不是"盒子",是"标签"

理解这一切,只需要接受一个设定:

Python 的变量名不存值,它只是一个贴在对象上的标签(名字绑定)。

a = 10

这行代码的底层动作是:右边先造出一个整数对象 10,然后让名字 a 指向它。a 本身不占地方存"10",它只是个引用,相当于便利贴。

赋值语句 c = a 更不是"复制了一个盒子"——它只是把新标签 c 也贴到同一个对象上:

a = [1, 2, 3]
c = a
c.append(4)
print(a)      # [1, 2, 3, 4]——a 和 c 贴的是同一个对象

这就是为什么 is 和 == 必须分开:== 比的是对象里的值,is 比的是"是不是同一个对象"。c is a 在这里是 True。

关键认知:变量是标签,那"改变量"就有两种完全不同的含义——把标签撕下来贴到别的对象上(重新绑定),还是钻进对象里面改内容。这两件事,对可变/不可变类型的效果天差地别。

3. 传参:传的是"标签的复印件"

调用函数时发生的事,可以用一句话说清:

函数收到的是实参引用的副本——一个新标签,贴到同一个对象上。

def append_one(lst):     # lst 是新标签,和 b 贴同一个列表
    lst.append(1)        # 钻进对象改内容 → b 看得见

def add_one(x):          # x 是新标签,和 a 贴同一个 10
    x = x + 1            # 撕下 x,贴到一个新对象 11 上 → a 无感

现在回头看第 1 节的两个现象,全部解释通了:

函数里的动作 实际发生了什么 外部看得见吗
lst.append(1) 通过标签钻进对象,改内容 看得见(对象被改了)
x = x + 1 重新绑定:x 指向新对象 看不见(a 还贴着老对象)

注意一个细节:x = x + 1 里的 + 1 其实也没"修改"整数对象——整数是不可变的,+ 只会造出一个新对象。所以严格说,不可变类型在函数里连"改内容"这个操作都不存在,你只能换绑。

4. mutable vs immutable:一张表说清

类型 常见成员 能"钻进对象改内容"吗 传参后的表现
不可变 int、float、str、tuple、frozenset 不能 函数内重新赋值,外部无感
可变 list、dict、set、bytearray 能 函数内改内容,外部同步看见

这张表就是全部规则。所谓"Python 是值传递还是引用传递"的争论,八成是把这两种表现混为一谈了。

再加一层保险:即使传进去的是可变对象,只要你在函数里写 lst = [新列表],那也是重新绑定——外部照样看不见。判定标准永远是那句:这行代码是"改内容"还是"换标签"。

5. 经典陷阱:默认参数为什么"记仇"

def bug(item, target=[]):
    target.append(item)
    return target

print(bug(1))    # [1]
print(bug(2))    # [1, 2]?!说好的默认空列表呢

陷阱根源:默认参数只在函数定义时求值一次,那个 [] 从始至终是同一个对象——所有没传 target 的调用,都在往同一个列表里塞东西。

正确写法:用 None 当哨兵,函数体内再创建:

def fixed(item, target=None):
    if target is None:
        target = []
    target.append(item)
    return target

这个坑能坑住人,靠的正是"可变对象 + 引用共享"两个知识点叠加。反过来,不可变类型做默认参数(如 def f(n=0))就安全——反正没人能改它。

6. 同类陷阱:+= 不总是等于 +

+= 对可变类型是"就地修改"(调用 __iadd__),对不可变类型是"重新绑定":

a = [1, 2]
b = a
a += [3]          # 就地改:a 和 b 还是同一个对象
print(b)          # [1, 2, 3]

x = 1
y = x
x += 1            # 重新绑定:y 无感
print(y)          # 1

同样一个 +=,行为分裂成两半。面试官爱问这个,不是爱抠字眼,是在考察你有没有"可变/不可变"这根弦。

7. 一句话总结

  • 变量是贴在对象上的标签,赋值是贴新标签,不是复制内容;
  • 传参传的是引用的副本——新标签贴老对象;
  • 能不能影响外部,只看一件事:改内容(可变)还是换标签(重新绑定);
  • 所以 Python 的准确叫法是 传对象引用(pass by object reference)。

把这四句话想明白,比背"值传递/引用传递"任何一个结论都管用。


下一篇:《Python 的垃圾回收到底回收了谁?引用计数+分代回收一次讲清》——一个 del 之后,对象在内存里经历了什么。关注不迷路。

相关文章
|
22天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
9223 29
|
21天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
4539 16
|
8天前
|
存储 人工智能 并行计算
大模型本地部署终端选型方法论:以 Qwen3.8-27B 为例的四档分层完整流程
本文提出一套大模型本地部署终端选型方法论:定约束、定档位、定框架、定参数四步决策法,配合入门、主力、质量、无损四档分层模型。以 Qwen3.8-27B 实测数据为例,逐环节解读显存、带宽、存储、散热、系统、预算等要素,给出面向不同预算的优选方案、决策自查清单与市场观察框架。文末前瞻 AI 笔记本的 CPU+GPU 与统一内存两条路线,论证四步决策法在新品类上的延续性。
|
20天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
2403 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
7天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型深度拆解:原理解读、实战测评与保姆级落地教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为**System One Model(系统一模型)**,对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
568 1
|
2天前
|
存储 缓存 测试技术
QWT 3D 模块重构记:旧渲染管线改进介绍及实时瀑布图示例
QWT 3D模块完成重大重构:解耦窗口与图形(Plot+Item),摒弃OpenGL 1.x固定管线,迁至Core Profile着色器渲染;支持多图元同场景叠加,并以实时3D瀑布图验证——滑动窗口、固定色域、64帧×256点达61fps。兼容Qt 5.12+/6,LGPL协议。
153 120
|
9天前
|
人工智能 Linux Windows
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
千问办公(QwenWork)是阿里云推出的AI智能办公平台,支持网页端直接使用及Windows/Mac/Linux客户端下载。提供PPT生成、财报分析、网页搭建等AI功能,个人版免费,企业版198元/席/月。详情见官网qwenwork.cn或阿里云产品页。
1129 0
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
|
14天前
|
Windows
【保姆级】.NET Framework 3.5离线安装教程(2026最新实测)
.NET Framework 3.5是微软经典运行库,专为兼容老软件、老游戏设计。Win7自带,Win10/11需手动启用(在线或离线安装)。它与4.x系列并存不冲突,缺它会导致“找不到组件”报错。本文详解两种安装方式及常见问题解决,小白也能轻松上手。(239字)
1675 0
|
3天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型全解析:核心原理拆解,性能实战测评与落地部署教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为System One Model(系统一模型),对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
352 0