默认参数里的列表,为什么会记住上一次调用
把空列表写在函数签名里,看起来每次调用都会得到一个新列表。实际上连续两次追加后,第二次结果往往包含第一次的数据,测试之间也可能互相污染。
▶ 本文含视频讲解▶ 教学视频手动播放 · 英语讲解
Python Tutorial for Beginners
Python 入门课程作为语法与编程背景复习;本文使用的较新标准库特性不保证在该课程中逐项覆盖。此为外部原版课程,多篇笔记可能共用;未剪辑为本文专属视频。
播放器需要能访问 YouTube 的网络;若这里无法加载,可打开原视频。本文与本地图解仍可独立阅读。
问题从哪里出现
把空列表写在函数签名里,看起来每次调用都会得到一个新列表。实际上连续两次追加后,第二次结果往往包含第一次的数据,测试之间也可能互相污染。
理解核心机制
默认表达式在函数定义执行时求值,而不是在每次调用时求值。对于需要独立容器的参数,可用 None 作为缺省标记,在函数内部创建列表。若 None 本身有业务含义,则使用独立的哨兵对象。
动手做一个小实验
Python 3.11 或更新版本,仅使用标准库;将示例保存为 demo.py 后执行 python3 demo.py。
def append_item(value, items=None):
if items is None:
items = []
items.append(value)
return items
first = append_item("java")
second = append_item("python")
assert first == ["java"] and second == ["python"]
print(first, second)适用边界与常见误区
传入显式列表后,函数仍会修改它;修复默认参数并不等于保证无副作用。接口必须说明是否修改调用方的对象,不能只依赖类型提示表达这一点。
继续练习
分别省略参数、传入空列表、连续复用同一列表,观察对象标识和内容。再设计一个返回新列表且不修改输入的版本。