2012-08-30 31 views
1

可能重複:
「Least Astonishment」 in Python: The Mutable Default Argument參數值正確性

當我閱讀下面的講義:http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables

我碰到下面的例子。基本上,它聲稱:

def bad_append(new_item, a_list=[]): 
    a_list.append(new_item) 
    return a_list 

不追加項目名單,因爲a_list在在函數定義時計算的最佳途徑。

取而代之的是,更好的選擇是:

def good_append(new_item, a_list=None): 
    if a_list is None: 
     a_list = [] 
    a_list.append(new_item) 
    return a_list 

,因爲它定義了功能的運行時變量。

來自C背景,是不是a_list這裏是一個局部變量?它如何將一個函數調用的值存儲到另一個函數調用中?此外,有人可以詳細說明爲什麼第二個例子比第一個更好嗎?在定義中定義函數有什麼問題?它似乎不會覆蓋原始值或任何東西。

謝謝!

+0

我想你可以閱讀以下內容:http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – Abgan

+0

看看http://docs.python .org/faq/design.html – Pramod

+1

我認爲這將是這個問題的第78個重複。 –

回答

2

一個簡單的答案是,def語句創建一個對象,並在對象執行時(當執行def行時),創建一個新的列表對象並將其附加到該對象(在這種情況下,該對象是一個功能)。

在後續執行中 - 您可能會期待的是生成一個新列表;但實際上當功能定義第一次運行時創建的同一個對象徘徊;並且該對象的所有「成員」保持不變。這就是爲什麼它不斷添加到相同的列表。

它被認爲是不好的原因是因爲你可能期望從參數(在每次執行時產生一個新列表)不是這個語句所做的。這就是爲什麼更好的模式是通過None或其他空白對象。

考慮以下幾點:

>>> bad_append('foo') 
['foo'] 
>>> bad_append('bar') 
['foo', 'bar'] 
>>> bad_append('zoo') 
['foo', 'bar', 'zoo'] 
>>> bad_append('bar',[]) 
['bar'] 
>>> bad_append('bar') # what? 
['foo', 'bar', 'zoo', 'bar'] 

正如你可以看到,當我在一個新的列表通過,在下次執行不沾左右;而是仍然執行def時生成的原始列表。

欲瞭解更多信息 - 請參閱this excellent explanation from effbot。