python函数默认参数若为可变对象会在定义时创建一次并多次调用间共享,易引发累积错误;应使用none作默认值并在函数内初始化新对象。

Python中默认参数如果使用可变对象(如列表、字典、集合),会在函数定义时被创建一次,并在多次调用间共享——这不是bug,而是设计使然,但极易引发隐蔽错误。
问题根源:默认参数只在函数定义时求值一次
Python函数的默认参数在def语句执行时就被实例化并绑定到函数对象上,而不是每次调用时重新生成。这意味着:
- 若默认参数是可变对象(如
[]或{}),它的内容会随函数调用被持续修改 - 后续调用若不传参,将复用之前已修改过的对象,而非一个“新鲜”的空列表
典型错误示例与后果
看这段代码:
def add_item(item, items=[]):
items.append(item)
return items
<p>print(add_item('a')) # ['a']
print(add_item('b')) # ['a', 'b'] ← 意外!第二次调用没传items,却沿用了第一次调用后已被修改的列表,导致结果累积。
立即学习“Python免费学习笔记(深入)”;
安全写法:用None作占位,内部创建新对象
正确做法是把默认值设为不可变的None,在函数体内判断并初始化:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
<p>print(add_item('a')) # ['a']
print(add_item('b')) # ['b'] ← 符合预期对字典等其他可变类型同理:data=None → if data is None: data = {}。
特殊情况提醒:类属性与闭包中也要警惕
该机制不仅影响函数默认参数,还可能出现在:
- 类的可变类属性(如
class A: cache = [])——所有实例共享同一列表 - 闭包内对外部可变变量的引用(尤其在循环中生成lambda时)
本质都是“对象被多次引用+原地修改”,核心思路始终是:需要新对象时,就明确创建,别依赖共享默认值。










