當咱們在構建一個函數或者方法時,若是想使函數中的一個或者多個參數使可選的,而且有一個默認值,那麼能夠在函數定義中給參數指定一個默認值,而且放到參數列表的最後就好了。好比:python
def func(a, b=42): print(a, b) func(1) #a=1, b=42 func(1,2) #a=1, b=2
若是默認參數使一個能夠修改的容器,好比一個列表,集合或者字典,可使用None做爲默認值。好比:app
#使用列表list做爲默認值 def func(a, b=None): if b is None: b = [] ···
可是,若是你並非想提供一個默認值,而僅僅知識想測試下某個默認參數是否是有值傳遞進來,能夠這樣寫:函數
_no_value = object() def func(a, b=_no_value): if b is _no_value: print("b沒有值") else: print(a, b) func(1) # b沒有值 func(1, None) # 1 None
仔細經過測試能夠發現,傳遞一個None值和不傳值兩種狀況是有差異的。測試
默認參數的值僅僅在函數定義的時候賦值一次,示例代碼以下:spa
x = 42 def func(a, b=x): print(a, b) func(1) #1 42 x = 23 func(1) #1 42
從上面例子中能夠看出,當咱們改變x的值的對默認參數值並無影響,這是由於在函數定定義的時候就已經肯定了它的默認值了。code
默認參數值的類型應該是不可變對象,好比None,True,False,數字或字符串,而不能使用列表,字典等可變類型。對象
不要像下面這樣寫代碼:blog
def func(a, b=[]): #不能這麼寫 ···
若是這樣寫了,當默認值在某些地方被修改以後,程序就會出現問題。字符串
這些被修改的程序會影響到下次調用這個參數時的默認值。好比:it
def func(a, b=[]): return b x = func(1) print(x) #[] x.append("a") x.append("b") print(x) #['a', 'b'] y = func(1) print(y) #['a', 'b']
能夠看到,b的默認值從一個空list,變成了[「a」, 「b」],這種不會是你想要的默認參數。
爲了不這種狀況的發生,最好是將默認值設置爲None,而後在函數裏面檢查它。
可是在將默認值設置爲None以後,測試None值時使用is操做符是很重要的,is是這種方法的關鍵點。
有人可能會這樣寫:
def func(a, b=None): if not b: b = [] ···
這麼寫有有一個問題,就是雖然None確實會被當成False,可是還有其餘的對象(好比長度爲0的字符串,列表,元組,字典等)都會被看成False。所以上面的代碼會誤將一些其餘輸入也會看成沒有輸入。好比:
def func(a, b=None): if not b: b = [] return b print(func(1)) # [] print(func(1, [])) # [] print(func(1, 0)) # [] print(func(1, "")) # []
從結果中就能夠看到,b的值並無發生改變,這不是咱們想要的結果。
當一個函數須要測試某個可選參數是否被使用者傳遞進來。這個時候須要當心的是不能用某個默認值,好比None,0或者False值來測試用戶提供的值(由於這些值都是合法的值,是可能被用戶傳遞進來的)。
你能夠建立一個獨一 無二的私有對象實例,就像上面的_no_value變量同樣。在函數裏面,你能夠經過檢查被傳遞參數值跟這個實例是否同樣來判斷。
這裏的思路就是用戶不可能去傳遞這個_no_value實例做爲輸出。所以這裏經過檢查這個值就能肯定某個參數是否被傳遞進來了。