可變的預設引數

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]