今天想編寫個Trie樹的小東西,沒想到居然遇到python中的一個很知名的坑,看似沒毛病的代碼,就是得不到正確結果,最后在stackoverflow上才尋得大牛解釋。故記錄如下。
大致是這樣一個問題
def fun(a=[]): a.append(1) print a #執行3次fun() 預料結果應該是[1] [1] [1] 實際結果如下 fun() #[1] fun() #[1,1] fun() #[1,1,1] ...
這個問題叫做default mutable parameter values,為何會發生這樣的結果呢?
不急,舉個簡單的例子
def fun1(a):
a.append(1)
print a
b = []
fun1(b) #[1]
fun1(b) #[1,1]
fun1(b) #[1,1,1]
這個結果應該再清楚不過吧,回到最前面的問題,你可以簡單的理解[]就是全局作用域中的一個對象。
詳細說明如下:
在python中,函數是一等公民,這種編程泛型叫做函數式編程。這里不說函數,說function可能更好一些。
def一個function,是一個執行語句。其目的是把一個當前環境function的名字和一個function對象綁定起來。這個function對象包括一個對function的引用,也就是說通過這個function對象可以調用function。function的body是不會執行的,只有在function被調用時才會執行。
那么默認函數參數呢?
Default parameter values are evaluated when the function definition is executed.
也就是說默認函數參數是在寫def時就已經被賦值(引用)了!
這樣你可以把默認參數理解成function對象的一個類似於'member variable'之類的東西來對待!!
這也就是說如果默認參數是可變的,如果function改變了這個參數(append or something else),那么這個參數就會改變的!
再看個小例子
b = []
def fun(a=b): #在執行這個def時已經把a綁定到b了
a.append(1)
..
這下子是不是有種明朗的感覺?
如何消除這個問題呢,一種方法如下
def fun(a=None):
if a == None:
a=[]
...
這樣每個a就是獨立的了。
