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免费学习笔记(深入)”;
本文档主要讲述的是Python之模块学习;python是由一系列的模块组成的,每个模块就是一个py为后缀的文件,同时模块也是一个命名空间,从而避免了变量名称冲突的问题。模块我们就可以理解为lib库,如果需要使用某个模块中的函数或对象,则要导入这个模块才可以使用,除了系统默认的模块(内置函数)不需要导入外。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
正确写法:用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提示,确认参数类型是否隐含可变性









