Python 函数默认参数是可变对象时为什么会“记住”上一次值?

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

为什么 def func(x=[]) 的默认列表会累积值?

因为 Python 在函数定义时就创建并复用同一个可变对象,而不是每次调用都新建。默认参数的值在 def 语句执行时求值一次,之后所有未传参的调用都共享这个对象。

哪些对象会出这个问题?

所有可变对象都可能——但最常见的是 []{}set()。不可变对象如 None0"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,会导致误判。

有没有例外或隐蔽坑?

有。比如嵌套结构:def f(data={"items": []}) 看似安全,其实 data["items"] 还是共享的;再比如类属性中用默认可变参数,也会跨实例污染。最稳妥的习惯是:只要涉及可变对象,默认值一律设为 None,并在函数开头做初始化。