默認參數(shù)很有用怕吴,但使用不當拒垃,也會掉坑里停撞。默認參數(shù)有個最大的坑,演示如下:
先定義一個函數(shù)悼瓮,傳入一個list戈毒,添加一個END再返回:
def add_end(L=[]):
L.append('END')
return L
當你正常調(diào)用時,結果似乎不錯:
>>> add_end([1, 2, 3])
[1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
當你使用默認參數(shù)調(diào)用時横堡,一開始結果也是對的:
>>> add_end()
['END']
但是埋市,再次調(diào)用add_end()時,結果就不對了:
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
很多初學者很疑惑命贴,默認參數(shù)是[]道宅,但是函數(shù)似乎每次都“記住了”上次添加了'END'后的list。
原因解釋如下:
Python函數(shù)在定義的時候胸蛛,默認參數(shù)L的值就被計算出來了污茵,即[],因為默認參數(shù)L也是一個變量葬项,它指向?qū)ο骩]泞当,每次調(diào)用該函數(shù),如果改變了L的內(nèi)容民珍,則下次調(diào)用時零蓉,默認參數(shù)的內(nèi)容就變了笤受,不再是函數(shù)定義時的[]了。
所以敌蜂,定義默認參數(shù)要牢記一點:默認參數(shù)必須指向不變對象箩兽!
要修改上面的例子,我們可以用None這個不變對象來實現(xiàn):
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
現(xiàn)在章喉,無論調(diào)用多少次汗贫,都不會有問題:
>>> add_end()
['END']
>>> add_end()
['END']
為什么要設計str、None這樣的不變對象呢秸脱?因為不變對象一旦創(chuàng)建落包,對象內(nèi)部的數(shù)據(jù)就不能修改,這樣就減少了由于修改數(shù)據(jù)導致的錯誤摊唇。此外咐蝇,由于對象不變,多任務環(huán)境下同時讀取對象不需要加鎖巷查,同時讀一點問題都沒有有序。我們在編寫程序時,如果可以設計一個不變對象岛请,那就盡量設計成不變對象旭寿。