2012-07-06 83 views
3

今天我探索的Python 怪異行爲。舉個例子:如何強制Python在循環內創建新變量/新範圍?

closures = [] 
for x in [1, 2, 3]: 
    # store `x' in a "new" local variable 
    var = x 

    # store a closure which returns the value of `var' 
    closures.append(lambda: var) 

for c in closures: 
    print(c()) 

上面的代碼打印

3 
3 
3 

但我想它打印

1 
2 
3 

我解釋這種行爲對自己說,var始終是相同的局部變量(和python不會像在其他語言中那樣創建一個新的)。我如何修復上面的代碼,以便每個閉包都會返回另一個值?

+0

提示:在Python中引入了一個新的變量作用域? – 2012-07-06 16:49:13

+0

剛剛看到http://stackoverflow.com/questions/7546285/creating-lambda-inside-a-loop?rq=1是一個重複的問題。我怎樣才能關閉這個或我應該刪除它? – 2012-07-06 16:49:38

+0

@tampis:只需投票結束 - 版主將最終決定是否合併或刪除此問題。 – 2012-07-06 16:51:38

回答

8

要做到這一點,最簡單的方法是使用默認參數爲您的拉姆達,這樣的x當前值綁定的的var功能的默認參數,而不是擡頭中含有範圍在每次調用:

closures = [] 
for x in [1, 2, 3]: 
    closures.append(lambda var=x: var) 

for c in closures: 
    print(c()) 

或者,你可以創建一個閉包(你有什麼是不封閉的,因爲在全球被創建的每個功能SCOP E):

make_closure = lambda var: lambda: var 
closures = [] 
for x in [1, 2, 3]: 
    closures.append(make_closure(x)) 

for c in closures: 
    print(c()) 

make_closure()也可以寫成這樣,這可能使其更易於閱讀:

def make_closure(var): 
    return lambda: var 
+1

+1對於很好的解釋 – 2012-07-06 16:53:47

6

不能創建在循環內的局部範圍內的新變量。無論您選擇何種名稱,您的功能將始終是該名稱的封閉並使用其最新值。

解決這個問題的最簡單的方法是使用關鍵字參數:

closures = [] 
for x in [1, 2, 3]: 
    closures.append(lambda var=x: var) 
+0

感謝您的編輯,現在可以+1。 – 2012-07-06 16:56:49

1

在你的榜樣,var總是綁定到循環的最後一個值。您需要使用closures.append(lambda var=var: var)將其綁定在lambda表達式中。