Python可变默认参数

示例

def foo(li=[]):
    li.append(1)
    print(li)

foo([2])
# 出:[2,1]
foo([3])
# 出:[3,1]

该代码的行为符合预期,但是如果我们不传递参数怎么办?

foo()
# 出:[1]符合预期...

foo()
# 出:[1,1]与预期不符...

这是因为函数和方法的默认参数是在定义时而不是运行时求值的。因此,我们只有一个li列表实例。

解决方法是对默认参数仅使用不可变类型:

def foo(li=None):
    if not li:
        li = []
    li.append(1)
    print(li)

foo()
# 出:[1]

foo()
# 出:[1]

尽管改进并且可以if not li正确评估为False,但许多其他对象也可以这样做,例如零长度序列。以下示例参数可能会导致意外的结果:

x = []
foo(li=x)
# 出:[1]

foo(li="")
# 出:[1]

foo(li=0) 
# 出:[1]

惯用的方法是直接检查None对象的参数:

def foo(li=None):
    if li is None:
        li = []
    li.append(1)
    print(li)

foo()
# 出:[1]