Python函数默认参数若为可变对象(如列表、字典),会在定义时创建并复用,导致状态累积;正确做法是用None作默认值并在函数内初始化。

Python函数的默认参数如果使用可变对象(如列表、字典、集合),会在函数定义时被创建一次,并在多次调用间共享,导致“意外”的状态累积——这不是bug,而是设计使然,但极易引发隐蔽错误。
为什么默认参数会“记住”上次修改?
Python中,默认参数在函数定义时求值并绑定,而非每次调用时重新创建。可变对象(如[]或{})一旦被修改,下次调用仍指向同一内存地址。
例如:
def add_item(item, lst=[]):
lst.append(item)
return lst
print(add_item('a')) # ['a']
print(add_item('b')) # ['a', 'b'] ← 意外!
立即学习“Python免费学习笔记(深入)”;
正确写法:用None作占位符
标准解法是将默认参数设为None,并在函数体内显式创建新对象:
- 用
lst=None代替lst=[] - 函数开头检查
if lst is None: lst = [] - 字典、集合同理:
dict=None→if dct is None: dct = {}
哪些对象属于“危险默认参数”?
所有可变内置类型都需警惕:
- 列表(
[])、字典({})、集合(set()) - 自定义类的实例(若其属性可变且未重载
__copy__等) - NumPy数组、pandas DataFrame 等可变容器
不可变类型(如int、str、tuple、FrozenSet)则安全,因为无法原地修改。
调试与自查小技巧
遇到疑似默认参数问题时,可快速验证:
- 打印参数的
id():连续调用是否返回相同ID? - 检查函数
func.__defaults__,查看实际存储的默认值 - 用
help(func)或IDE提示,确认参数类型是否隐含可变性


















