为什么Python函数会保留可变默认关键字参数的最后值?
Python可变默认参数的行为说明
你遇到的是Python非常经典的可变默认参数坑,核心逻辑如下:
- Python函数的默认参数绑定发生在函数定义阶段,而非每次函数调用时
- 如果默认参数是不可变类型(整数、字符串、元组等),修改操作会生成新对象,不会影响默认参数本身,符合直觉
- 如果默认参数是可变类型(字典、列表、集合等),所有不传该参数的函数调用,都会复用同一个初始化的可变对象,修改操作会直接修改这个默认绑定的对象
对应你给出的代码:
def foo(x, obj={}): obj['x'] = x return obj values = [] for i in range(3): obj = foo(i) values.append(obj) values = [v['x'] for v in values] print(values)
当Python解析到def foo(x, obj={}):这行函数定义时,就已经生成了一个空字典对象,绑定为obj参数的默认值。后续三次调用foo(i)都没有传入obj参数,所以每次操作的都是同一个字典对象:
- i=0时,字典被修改为
{'x': 0},该字典的引用被添加到values列表 - i=1时,同一个字典被修改为
{'x': 1},values里已存的第一个元素因为指向同一个字典,值也同步更新 - i=2时,同一个字典被修改为
{'x': 2},values里三个元素都是该字典的引用,最终取值时三个都返回2
你选择每次调用手动传{}确实可以解决问题,此时每次调用都会生成新的空字典传入,不会复用默认的绑定对象。更通用的工程规范写法是用None作为可变参数的默认占位,在函数内部初始化可变对象,避免每次调用手动传参的冗余:
def foo(x, obj=None): # 每次调用不传obj时,都会在函数内部生成新的空字典 if obj is None: obj = {} obj['x'] = x return obj
内容的提问来源于stack exchange,提问作者sagar
相关产品推荐
相关产品推荐

