Python如何定義有默認(rèn)參數(shù)的函數(shù)
問題
你想定義一個函數(shù)或者方法,它的一個或多個參數(shù)是可選的并且有一個默認(rèn)值。
解決方案
定義一個有可選參數(shù)的函數(shù)是非常簡單的,直接在函數(shù)定義中給參數(shù)指定一個默認(rèn)值,并放到參數(shù)列表最后就行了。例如:
def spam(a, b=42): print(a, b)spam(1) # Ok. a=1, b=42spam(1, 2) # Ok. a=1, b=2
如果默認(rèn)參數(shù)是一個可修改的容器比如一個列表、集合或者字典,可以使用None作為默認(rèn)值,就像下面這樣:
# Using a list as a default valuedef spam(a, b=None): if b is None: b = [] ...
如果你并不想提供一個默認(rèn)值,而是想僅僅測試下某個默認(rèn)參數(shù)是不是有傳遞進(jìn)來,可以像下面這樣寫:
_no_value = object()def spam(a, b=_no_value): if b is _no_value: print(’No b value supplied’) ...
我們測試下這個函數(shù):
>>> spam(1)No b value supplied>>> spam(1, 2) # b = 2>>> spam(1, None) # b = None>>>
仔細(xì)觀察可以發(fā)現(xiàn)到傳遞一個None值和不傳值兩種情況是有差別的。
討論
定義帶默認(rèn)值參數(shù)的函數(shù)是很簡單的,但絕不僅僅只是這個,還有一些東西在這里也深入討論下。
首先,默認(rèn)參數(shù)的值僅僅在函數(shù)定義的時候賦值一次。試著運行下面這個例子:
>>> x = 42>>> def spam(a, b=x):... print(a, b)...>>> spam(1)1 42>>> x = 23 # Has no effect>>> spam(1)1 42>>>
注意到當(dāng)我們改變x的值的時候?qū)δJ(rèn)參數(shù)值并沒有影響,這是因為在函數(shù)定義的時候就已經(jīng)確定了它的默認(rèn)值了。
其次,默認(rèn)參數(shù)的值應(yīng)該是不可變的對象,比如None、True、False、數(shù)字或字符串。 特別的,千萬不要像下面這樣寫代碼:
def spam(a, b=[]): # NO! ...
如果你這么做了,當(dāng)默認(rèn)值在其他地方被修改后你將會遇到各種麻煩。這些修改會影響到下次調(diào)用這個函數(shù)時的默認(rèn)值。比如:
>>> 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!’]>>>
這種結(jié)果應(yīng)該不是你想要的。為了避免這種情況的發(fā)生,最好是將默認(rèn)值設(shè)為None, 然后在函數(shù)里面檢查它,前面的例子就是這樣做的。
在測試None值時使用 is 操作符是很重要的,也是這種方案的關(guān)鍵點。 有時候大家會犯下下面這樣的錯誤:
def spam(a, b=None): if not b: # NO! Use ’b is None’ instead b = [] ...
這么寫的問題在于盡管None值確實是被當(dāng)成False, 但是還有其他的對象(比如長度為0的字符串、列表、元組、字典等)都會被當(dāng)做False。 因此,上面的代碼會誤將一些其他輸入也當(dāng)成是沒有輸入。比如:
>>> 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>>>
最后一個問題比較微妙,那就是一個函數(shù)需要測試某個可選參數(shù)是否被使用者傳遞進(jìn)來。 這時候需要小心的是你不能用某個默認(rèn)值比如None、 0或者False值來測試用戶提供的值(因為這些值都是合法的值,是可能被用戶傳遞進(jìn)來的)。 因此,你需要其他的解決方案了。
為了解決這個問題,你可以創(chuàng)建一個獨一無二的私有對象實例,就像上面的_no_value變量那樣。 在函數(shù)里面,你可以通過檢查被傳遞參數(shù)值跟這個實例是否一樣來判斷。 這里的思路是用戶不可能去傳遞這個_no_value實例作為輸入。 因此,這里通過檢查這個值就能確定某個參數(shù)是否被傳遞進(jìn)來了。
這里對 object() 的使用看上去有點不太常見。object 是python中所有類的基類。 你可以創(chuàng)建 object 類的實例,但是這些實例沒什么實際用處,因為它并沒有任何有用的方法, 也沒有任何實例數(shù)據(jù)(因為它沒有任何的實例字典,你甚至都不能設(shè)置任何屬性值)。 你唯一能做的就是測試同一性。這個剛好符合我的要求,因為我在函數(shù)中就只是需要一個同一性的測試而已。
以上就是Python如何定義有默認(rèn)參數(shù)的函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于Python定義有默認(rèn)參數(shù)的函數(shù)的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. PHP使用Swagger生成好看的API文檔2. 通過實例解析Python文件操作實現(xiàn)步驟3. Python3 json模塊之編碼解碼方法講解4. Python 利用Entrez庫篩選下載PubMed文獻(xiàn)摘要的示例5. ASP.NET MVC使用jQuery ui的progressbar實現(xiàn)進(jìn)度條6. ASP基礎(chǔ)知識VBScript基本元素講解7. Python 制作查詢商品歷史價格的小工具8. python使用jenkins發(fā)送企業(yè)微信通知的實現(xiàn)9. Python 合并拼接字符串的方法10. Python 如何調(diào)試程序崩潰錯誤

網(wǎng)公網(wǎng)安備