当使用具有可变默认类型的可选参数时(存在使用可选参数定义函数中所述),这可能会导致意外行为。
这个问题是因为一个函数的默认参数初始化一旦被该功能时,在点定义,并不能(像许多其他语言)当函数被称为。默认值存储在函数对象的__defaults__成员变量中。
def f(a, b=42, c=[]): pass print(f.__defaults__) # 输出:(42,[])
对于不可变类型(请参阅参数传递和可变性),这是没有问题的,因为没有方法可以对变量进行突变。只能重新分配它,而使原始值保持不变。因此,可以保证后续的具有相同的默认值。但是,对于可变类型,可以通过调用其各种成员函数来更改原始值。因此,不能保证对函数的连续调用具有初始默认值。
def append(elem, to=[]): to.append(elem) # This call to append() mutates the default variable "to" return to append(1) # 出:[1] append(2) # 将其附加到内部存储的列表中 # 出:[1,2] append(3, []) # 使用新创建的列表可以得到预期的结果 # 出:[3] # 不带参数再次调用它将再次添加到内部存储的列表中 append(4) # 出:[1、2、4]
注意:当将可变类型指定为默认属性时,某些IDE(如PyCharm)将发出警告。
如果要确保默认参数始终是在函数定义中指定的参数,则解决方案是始终使用不可变类型作为默认参数。
当需要将可变类型作为默认类型时,实现此目的的常见习惯是使用None(不可变)作为默认参数,然后将实际默认值分配给参数变量(如果等于)None。
def append(elem, to=None): if to is None: to = [] to.append(elem) return to