W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
你想定義一個函數或者方法,它的一個或多個參數是可選的并且有一個默認值。
定義一個有可選參數的函數是非常簡單的,直接在函數定義中給參數指定一個默認值,并放到參數列表最后就行了。例如:
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
>>>
仔細觀察可以發(fā)現到傳遞一個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!']
>>>
這種結果應該不是你想要的。為了避免這種情況的發(fā)生,最好是將默認值設為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
>>>
最后一個問題比較微妙,那就是一個函數需要測試某個可選參數是否被使用者傳遞進來。這時候需要小心的是你不能用某個默認值比如None、0或者False值來測試用戶提供的值(因為這些值都是合法的值,是可能被用戶傳遞進來的)。因此,你需要其他的解決方案了。
為了解決這個問題,你可以創(chuàng)建一個獨一無二的私有對象實例,就像上面的_no_value變量那樣。在函數里面,你可以通過檢查被傳遞參數值跟這個實例是否一樣來判斷。這里的思路是用戶不可能去傳遞這個_no_value實例作為輸入。因此,這里通過檢查這個值就能確定某個參數是否被傳遞進來了。
這里對 object()
的使用看上去有點不太常見。object
是python中所有類的基類。你可以創(chuàng)建 object
類的實例,但是這些實例沒什么實際用處,因為它并沒有任何有用的方法,也沒有哦任何實例數據(因為它沒有任何的實例字典,你甚至都不能設置任何屬性值)。你唯一能做的就是測試同一性。這個剛好符合我的要求,因為我在函數中就只是需要一個同一性的測試而已。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯系方式:
更多建議: