Bug排查
Python 可变默认参数陷阱:一个隐蔽的 Bug
Java NullPointerException 深度排查指南
常见 Bug 排查——Python 中 mutable default argument 陷阱(可变默认参数导致的共享状态Bug)
Java Bug排查:ConcurrentModificationException 并发修改异常深度解析
Java 并发 Bug - ConcurrentModificationException 排查与修复
Java 并发 Bug:ArrayList 的 ConcurrentModificationException
Python 可变默认参数陷阱:一次踩坑与彻底修复
本站点使用 MrDoc 构建
-
+
Python 可变默认参数陷阱:一个隐蔽的 Bug
> 分类:Bug 排查 | 语言:Python | 严重程度:🔴 高  ## Bug 现象 你写了一个函数,用空列表作为默认参数,结果第二次调用时竟然"记住"了上次的值: ```python def append_item(item, lst=[]): lst.append(item) return lst # 第一次调用 print(append_item(1)) # [1] ✅ 看起来没问题 # 第二次调用 print(append_item(2)) # [1, 2] ❌ 等等,为什么 1 还在? ``` 期望第二次调用返回 `[2]`,实际返回了 `[1, 2]`。更恐怖的是——第三次调用会返回 `[1, 2, 3]`,数据越积越多,完全不可控。  ## 根因分析 Python 的默认参数值在**函数定义时**(`def` 语句执行时)就被创建了,而不是在每次调用时创建。 也就是说,`lst=[]` 中的空列表 `[]` 是一个**可变对象**,它在 `def` 执行时被创建了一次,之后所有调用都**共享同一个列表对象**。 关键点: - `def` 语句只执行**1次** → 默认列表对象只创建**1次** - 每次调用函数时,如果不传 `lst` 参数,用的都是**同一个列表** - 列表的 `append` 操作是**原地修改**,不会创建新对象 这不是 Python 的 bug,而是设计如此。但对于初学者来说,这是一个非常隐蔽的陷阱。  ## 修复方案 **用 `None` 替代可变默认值,在函数体内创建新对象:** ```python # ✅ 正确写法 def append_item(item, lst=None): if lst is None: lst = [] # 每次调用都创建新列表 lst.append(item) return lst # 现在行为符合预期 print(append_item(1)) # [1] print(append_item(2)) # [2] ✅ print(append_item(3)) # [3] ✅ ``` 同样的模式适用于字典和集合: ```python # ❌ 危险 def add_config(key, value, config={}): config[key] = value return config # ✅ 安全 def add_config(key, value, config=None): if config is None: config = {} config[key] = value return config ```  ## 预防措施 1. **永远不要用可变对象做默认参数** — `list`、`dict`、`set` 都不行,用 `None` 替代 2. **代码审查时重点关注** — 搜索 `def.*=\[\]`、`def.*=\{\}`、`def.*=set()` 这些模式 3. **使用 Linter** — `flake8` / `pylint` / `ruff` 都会检测可变默认参数并报警告 4. **为有副作用的函数写单元测试** — 多次调用同一个函数,验证每次结果独立 5. **理解 Python 对象模型** — 可变对象是引用传递,不是值传递 ## 扩展阅读 - [Python 官方 FAQ: Why are default values shared between objects?](https://docs.python.org/3/faq/programming.html#why-are-default-values-shared-between-objects) - [Effective Python] Item 24: Use None and Docstrings to Specify Dynamic Default Arguments --- *本文由自动化工具生成,如有疑问欢迎评论交流。*
admin
2026年5月16日 18:15
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码