使用可选的可变参数定义函数
使用具有可变默认类型的可选参数时出现问题(在使用可选参数定义函数中进行了描述 ),这可能会导致意外行为。 ****
说明
这个问题是因为一个函数的默认参数初始化一旦被该功能时,在点定义,并不能 (像许多其他语言)当函数被称为。默认值存储在函数对象的 __defaults__
成员变量中。
def f(a, b=42, c=[]):
pass
print(f.__defaults__)
# Out: (42, [])
对于不可变类型(参见 Argument 传递和可变性 ),这不是问题,因为没有办法改变变量; 它只能被重新分配,保持原始值不变。因此,后续保证具有相同的默认值。但是,对于可变类型,通过调用其各种成员函数,原始值可以变异。因此,不保证对函数的连续调用具有初始缺省值。
def append(elem, to=[]):
to.append(elem) # This call to append() mutates the default variable "to"
return to
append(1)
# Out: [1]
append(2) # Appends it to the internally stored list
# Out: [1, 2]
append(3, []) # Using a new created list gives the expected result
# Out: [3]
# Calling it again without argument will append to the internally stored list again
append(4)
# Out: [1, 2, 4]
注意: 某些 IDE(如 PyCharm)会在将可变类型指定为默认属性时发出警告。
解
如果要确保默认参数始终是你在函数定义中指定的参数,那么解决方案是始终使用不可变类型作为默认参数。
当需要使用可变类型作为默认值时,实现此目的的常用习惯是使用 None
(不可变)作为默认参数,然后如果它等于 None
则将实际默认值分配给参数变量。
def append(elem, to=None):
if to is None:
to = []
to.append(elem)
return to