Python方法默认参数results=[]为何复用?是否为官方行为?
Python 可变默认参数的状态共享问题
版本信息
版本:Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]
代码示例
from dataclasses import dataclass class _Mixin: def vars_to_dct(self, results=[]): dct = self.to_dict() for k in dct.keys(): results.append(k) return results @dataclass class ClassA(_Mixin): a: str = "" b: str = "" @dataclass class ClassB(_Mixin): c: str = "" d: str = "" e: str = ""
测试结果
单独调用(符合预期)
a = ClassA() assert ["a", "b"] == a.vars_to_dct()
b = ClassB() assert ["c", "d", "e"] == b.vars_to_dct()
连续调用(触发异常)
a = ClassA() assert ["a", "b"] == a.vars_to_dct() b = ClassB() assert ["c", "d", "e"] == b.vars_to_dct() # 抛出AssertionError
实际返回结果:
b = ClassB() assert ["a", "b", "c", "d", "e"] == b.vars_to_dct()
显式传入参数(符合预期)
b = ClassB() assert ["c", "d", "e"] == b.vars_to_dct(results=[])
问题解析
这是Python可变默认参数的经典陷阱,和类变量/静态成员无关,核心逻辑如下:
- Python函数的默认参数仅在函数定义阶段初始化一次,而非每次调用时重新创建。像列表这类可变对象,初始化后会作为函数的固定属性存在,所有未显式传入参数的调用,都会复用同一个对象。
- 可以通过
print(_Mixin.vars_to_dct.__defaults__)验证:默认的results列表始终是同一个对象,每次调用append都会往该列表中添加元素,导致跨调用的状态残留。
修复方案
将默认参数设为None,在函数内部初始化新列表,确保每次调用都使用独立的列表对象:
class _Mixin: def vars_to_dct(self, results=None): if results is None: results = [] dct = self.to_dict() for k in dct.keys(): results.append(k) return results
内容的提问来源于stack exchange,提问作者Williams
相关产品推荐
相关产品推荐

