其實也不能說是陷阱,只是一個不容易注意到的地方,尤其是有其他java/c++類編程語言經驗的人員,這里涉及到python的一個特點,所以筆者說是陷阱只是一個噱頭而已。
def test(item, buf = []):
buf.append(buf)
print buf
非常簡單的一個函數,功能非常簡單,現在看下面的調用代碼
test('younger')
test('shen')
輸出:
['younger']
['younger', 'shen']
該函數初衷是希望當沒有提供默認的buff參數的時候,建立一個空的列表,然后把一個對象添加到該列表中,並且打印, 但是程序的執行似乎並沒有按照我們的意圖來執行,似乎每個函數都共享了buff,但是我們明明每次都在參數列表中初始化了buff變量,分析如下:
python中的def語句在每次執行的時候都初始化一個函數對象,這個函數對象就是我們要調用的函數,可以把它當成一個一般的對象,只不過這個對象擁有一個可執行的方法和部分屬性,對於參數中提供了初始值的參數,由於python中的函數參數傳遞的是對象,也可以認為是傳地址,只有def的時候初始化一次,然后在調用者和被調用者中都是共享的,所以在 func.func_defaults中只能看到一個默認參數,在該函數對象被初始化的時候就已經存在了。
解決這個問題可以用這個方法
def test(item, buf = None):
if buf is None:
buf = []
buf.append(item)
print buf
這樣在不給定buf參數的時候可以初始化一次buf,每次都是新的,所以不會出現上面的陷阱,其實這里的None只是占位符而已,用空[]也可以,只不過要需要這樣寫
def test(item, buf = []):
if len(buf) < 1:
buf = []
buf.append(item)
print buf
這樣也可以解決問題,只是看起開不太好而已。
近期除了使用django進行web開發之外,打算重新開始學習linux和操作系統的東西,近期會制定學習計划開始執行。