Python實戰從入門到精通第十四講——定義有默認參數的函數

定義一個函數或者方法,它的一個或多個參數是可選的並且有一個默認值。

定義一個有可選參數的函數是非常簡單的,直接在函數定義中給參數指定一個默認值,並放到參數列表最後就行了。例如:

def spam(a, b=42):
    print(a, b)

spam(1) # Ok. a=1, b=42
spam(1, 2) # Ok. a=1, b=2

如果默認參數是一個可修改的容器比如一個列表、集合或者字典,可以使用None作爲默認值,就像下面這樣:

# Using a list as a default value
def spam(a, b=None):
    if b is None:
        b = []

如果你並不想提供一個默認值,而是想僅僅測試下某個默認參數是不是有傳遞進來,可以像下面這樣寫:

_no_value = object()

def spam(a, b=_no_value):
    if b is _no_value:
        print('No b value supplied')

測試下這個函數:

>>> spam(1)
No b value supplied
>>> spam(1, 2) # b = 2
>>> spam(1, None) # b = None

仔細觀察可以發現到傳遞一個None值和不傳值兩種情況是有差別的。

定義帶默認值參數的函數是很簡單的,但絕不僅僅只是這個,還有一些東西在這裏也深入討論下。

首先,默認參數的值僅僅在函數定義的時候賦值一次。試着運行下面這個例子:

>>> x = 42
>>> def spam(a, b=x):
...     print(a, b)
...
>>> spam(1)
1 42
>>> x = 23 # Has no effect
>>> spam(1)
1 42

注意到當我們改變x的值的時候對默認參數值並沒有影響,這是因爲在函數定義的時候就已經確定了它的默認值了。

其次,默認參數的值應該是不可變的對象,比如None、True、False、數字或字符串。 特別的,千萬不要像下面這樣寫代碼:

def spam(a, b=[]): # NO!

如果你這麼做了,當默認值在其他地方被修改後你將會遇到各種麻煩。這些修改會影響到下次調用這個函數時的默認值。比如:

>>> def spam(a, b=[]):
...     print(b)
...     return b
...
>>> x = spam(1)
>>> x
[]
>>> x.append(99)
>>> x.append('Yow!')
>>> x
[99, 'Yow!']
>>> spam(1) # Modified list gets returned!
[99, 'Yow!']

這種結果應該不是你想要的。爲了避免這種情況的發生,最好是將默認值設爲None, 然後在函數裏面檢查它,前面的例子就是這樣做的。

在測試None值時使用 is 操作符是很重要的,也是這種方案的關鍵點。 有時候大家會犯下下面這樣的錯誤:

def spam(a, b=None):
    if not b: # NO! Use 'b is None' instead
        b = []

這麼寫的問題在於儘管None值確實是被當成False, 但是還有其他的對象(比如長度爲0的字符串、列表、元組、字典等)都會被當做False。 因此,上面的代碼會誤將一些其他輸入也當成是沒有輸入。比如:

>>> spam(1) # OK
>>> x = []
>>> spam(1, x) # Silent error. x value overwritten by default
>>> spam(1, 0) # Silent error. 0 ignored
>>> spam(1, '') # Silent error. '' ignored

 

發佈了367 篇原創文章 · 獲贊 188 · 訪問量 51萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章