可选参数可以有默认值,这是 Python 函数定义的一个很棒的特性,这样我们的 API 在进 化的同时能保证向后兼容。然而,我们应该避免使用可变的对象作为参数的默认值。
示例:
"""
不要使用可变类型作为函数的参数的默认值
"""
class HauntedBus:
def __init__(self, passengers=[]):
self.passengers = passengers
def pick(self, name):
self.passengers.append(name)
def drop(self, name):
self.passengers.remove(name)
if __name__ == "__main__":
# 当给参数传入值得时候
bus1 = HauntedBus(['Alice', 'Bill'])
print(bus1.passengers)
bus1.pick('Charlie')
bus1.drop('Alice')
print(bus1.passengers)
# 当个函数没有传入默认值得时候
bus2 = HauntedBus()
bus2.pick('mo')
print(bus2.passengers)
bus3 = HauntedBus()
print(bus3.passengers)
print(bus3.passengers is bus2.passengers)
print(dir(HauntedBus.__init__))
print(HauntedBus.__init__.__defaults__)
运行结果:
这里就会发现问题:bus3 的 passengers 的熟悉和bus2 的passengers 一致。
问题在于,没有指定初始乘客的 HauntedBus 实例会共享同一个乘客列表。出现这个问题的根源是,默认值在定义 函数时计算(通常在加载模块时),因此默认值变成了函数对象的属性。因此,如果默认 值是可变对象,而且修改了它的值,那么后续的函数调用都会受到影响。