You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用函数定义Python函数默认参数会引发信息泄露?

Python默认参数的陷阱:可变对象与不可变对象的差异

我尝试用另一个函数生成的标准字典作为函数默认参数,但第二次调用函数时,前一次运行的修改会泄露到第二次调用中。

问题复现代码

standard_list = ['a','b','c','d']
my_list = ['b','d']
my_second_list = ['a','b']

def init_dict():
    my_dict = {}
    for key in standard_list:
            my_dict[key]=0
    return my_dict

def create_shopping_dict(shopping_list, standard_dict=init_dict()):
    for key in shopping_list:
        standard_dict[key]=1
    return standard_dict

my_shopping_list = create_shopping_dict(my_list)

my_second_shopping_list = create_shopping_dict(my_second_list)
print(my_second_shopping_list)

预期输出

{'a': 1, 'b': 1, 'c': 0, 'd': 0}

实际输出

{'a': 1, 'b': 1, 'c': 0, 'd': 1}

可行的修改方案

将standard_dict的初始化移至函数内部即可解决问题,但我不理解原因:

def create_shopping_dict(shopping_list):
    standard_dict=init_dict()        
    for key in shopping_list:
        standard_dict[key]=1
    return standard_dict

另一个对比案例

如果说Python是存储参数值供后续调用而非使用默认值,以下代码应输出1和2,但实际输出1和1:

def test(a=0):
    a+=1
    return a

print(test())
print(test())

原因解释

核心逻辑是Python的默认参数只会在函数定义时计算一次,而非每次调用函数时重新生成:

  • 可变对象(如字典、列表):当init_dict()作为默认参数时,函数定义阶段就会执行该函数生成一个字典对象,后续所有未传standard_dict的调用都会复用这个同一个字典实例。第一次调用修改了它的键值对,第二次调用自然会读取到修改后的状态。
  • 不可变对象(如整数、字符串):test(a=0)中的0是不可变类型,a +=1并不会修改原来的默认参数0,而是创建一个新的整数对象(值为1)并赋值给局部变量a。每次调用时,默认参数都是最初的0,所以每次调用都会得到1。

总结

如果需要每次调用函数时都生成全新的默认对象,绝对不能将可变对象直接设为默认参数,正确的做法是在函数内部完成初始化,确保每次调用都能拿到独立的新对象,避免状态泄露。

内容的提问来源于stack exchange,提问作者mitikawa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 13:50:46