可变的默认参数

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

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

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

foo()
# Out: [1] As expected...

foo()
# Out: [1, 1]  Not as expected...

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

解决它的方法是仅使用不可变类型作为默认参数:

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

foo()
# Out: [1]

foo()
# Out: [1]

虽然改进虽然 if not li 正确地评估为 False,但许多其他对象也是如此,例如零长度序列。以下示例参数可能会导致意外结果:

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

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

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

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

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

foo()
# Out: [1]