Python不要使用可变对象作为函数的默认参数
中一个常见的陷阱,与可变默认参数有关。
让我们看看AutoParamGroup
类的__init__
方法定义:
def __init__(self, ref_mode=[], ref_value=[], ref_group_num=[], ref_interp_method=[], ref_gain_lux=0,param_list=[]):self.ref_mode = ref_modeself.ref_value = ref_valueself.ref_group_num = ref_group_numself.ref_interp_method = ref_interp_methodself.ref_gain_lux = ref_gain_luxself.param_list = param_list
这里的问题在于使用了可变对象(列表[]
)作为默认参数值。在Python中,默认参数值是在函数定义时就被创建的,而不是在函数调用时。这意味着所有使用默认参数的实例都会共享同一个列表对象。
要解决这个问题,推荐的做法是使用None
作为默认值,然后在__init__
方法中创建新的列表。以下是修正后的代码:
def __init__(self, ref_mode=None, ref_value=None, ref_group_num=None, ref_interp_method=None, ref_gain_lux=0, param_list=None):self.ref_mode = ref_mode if ref_mode is not None else []self.ref_value = ref_value if ref_value is not None else []self.ref_group_num = ref_group_num if ref_group_num is not None else []self.ref_interp_method = ref_interp_method if ref_interp_method is not None else []self.ref_gain_lux = ref_gain_luxself.param_list = param_list if param_list is not None else []
这样修改后:
- 每次创建新实例时都会创建新的列表对象
- 不同实例之间的列表将是独立的
- 不会出现数据残留的问题
这是Python中的一个经典问题,在使用可变对象(如列表、字典等)作为默认参数时经常会遇到。记住:永远不要使用可变对象作为函数的默认参数。