因为Python在函数定义时创建并复用同一可变对象,默认参数仅求值一次;常见问题对象有[]、{}、set();安全写法是用None作默认值并在函数内初始化。

为什么 def func(x=[]) 的默认列表会累积值?
因为 Python 在函数定义时就创建并复用同一个可变对象,而不是每次调用都新建。默认参数的值在 def 语句执行时求值一次,之后所有未传参的调用都共享这个对象。
哪些对象会出这个问题?
所有可变对象都可能——但最常见的是 []、{}、set()。不可变对象如 None、0、"abc" 没这问题,因为它们无法被原地修改。
-
[]:调用.append()或+=后,下次调用仍看到旧元素 -
{}:用.update()或直接赋值键后,状态保留 -
set():用.add()添加后,集合持续增长
怎么安全地写带默认可变参数的函数?
标准解法是用 None 作默认值,在函数体内显式初始化:
def append_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
注意必须用 is None 判断,不能用 if not lst——空列表也是 falsy,会导致误判。
立即学习“Python免费学习笔记(深入)”;
有没有例外或隐蔽坑?
有。比如嵌套结构:def f(data={"items": []}) 看似安全,其实 data["items"] 还是共享的;再比如类属性中用默认可变参数,也会跨实例污染。最稳妥的习惯是:只要涉及可变对象,默认值一律设为 None,并在函数开头做初始化。










