4 回答

TA貢獻1802條經驗 獲得超5個贊
您可以使用具有默認值的參數強制捕獲變量:
>>> for i in [0,1,2,3]:
... adders[i]=lambda a,i=i: i+a # note the dummy parameter with a default value
...
>>> print( adders[1](3) )
4
我們的想法是聲明一個參數(巧妙地命名i)并給它一個你想要捕獲的變量的默認值(值 i)

TA貢獻1864條經驗 獲得超2個贊
為了完整性,您對第二個問題的另一個答案是:您可以在functools模塊中使用partial。
通過從運營商導入add,Chris Lutz提出的示例變為:
from functools import partialfrom operator import add # add(a, b) -- Same as a + b.adders = [0,1,2,3]for i in [0,1,2,3]: # store callable object with first argument given as (current) i adders[i] = partial(add, i) print adders[1](3)

TA貢獻1818條經驗 獲得超7個贊
請考慮以下代碼:
x = "foo"def print_x(): print x x = "bar"print_x() # Outputs "bar"
我想大多數人都不會發現這種混亂。這是預期的行為。
那么,為什么人們認為它在循環中完成時會有所不同?我知道我自己犯了這個錯誤,但我不知道為什么。這是循環?或者也許是lambda?
畢竟,循環只是一個較短的版本:
adders= [0,1,2,3]i = 0adders[i] = lambda a: i+a i = 1adders[i] = lambda a: i+a i = 2adders[i] = lambda a: i+a i = 3adders[i] = lambda a: i+a

TA貢獻1876條經驗 獲得超5個贊
你的第二個問題已得到解答,但至于你的第一個問題:
封閉捕獲到底是什么?
Python中的范圍是動態的和詞匯的。閉包將始終記住變量的名稱和范圍,而不是它指向的對象。由于示例中的所有函數都在同一作用域中創建并使用相同的變量名,因此它們始終引用相同的變量。
編輯:關于如何克服這個問題的另一個問題,有兩種方法可以想到:
最簡潔但不嚴格等同的方式是Adrien Plisson推薦的方式。使用額外參數創建lambda,并將額外參數的默認值設置為要保留的對象。
每次創建lambda時,創建一個新范圍會更冗長但更少hacky:
>>> adders = [0,1,2,3]>>> for i in [0,1,2,3]:... adders[i] = (lambda b: lambda a: b + a)(i)... >>> adders[1](3)4>>> adders[2](3)5
這里的范圍是使用一個新函數(lambda,為簡潔起見)創建的,它綁定了它的參數,并傳遞你想要綁定的值作為參數。但是,在實際代碼中,您很可能會使用普通函數而不是lambda來創建新范圍:
def createAdder(x): return lambda y: y + x adders = [createAdder(i) for i in range(4)]
添加回答
舉報