2 回答

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超4個(gè)贊
Python使用閉包捕獲對(duì)原始變量的引用。這些lambda對(duì)象保留了對(duì)i名稱(chēng)的引用,可以通過(guò)該引用訪(fǎng)問(wèn)值。這意味著i變量在f完成后將繼續(xù)存在。
您可以.__closure__在lambda對(duì)象的元組中內(nèi)省此閉包;函數(shù)具有相同的屬性:
>>> L[0].__closure__
(<cell at 0x1077f8b78: int object at 0x107465880>,)
>>> L[0].__closure__[0]
<cell at 0x1077f8b78: int object at 0x107465880>
>>> L[0].__closure__[0].cell_contents
4
這也是列表中所有l(wèi)ambda都L引用value4而不是0到4的原因。它們都引用相同的閉包:
>>> L[0].__closure__[0] is L[1].__closure__[0]
True
閉包引用變量,而不是定義閉包時(shí)該變量的值。循環(huán)的i最后一次設(shè)置為4,因此在查找時(shí),對(duì)于列表中的所有l(wèi)ambda,都會(huì)找到ilambda閉包4。
如果您希望lambdai在循環(huán)期間引用value,請(qǐng)?jiān)陉P(guān)鍵字參數(shù)中捕獲它:
def f():
L = []
for i in range(5):
L.append(lambda x, i=i: i ** x)
return L
現(xiàn)在i是lambda的局部變量,而不是閉包。
或者,創(chuàng)建一個(gè)全新的范圍來(lái)從中繪制閉合:
def create_lambda(i):
return lambda x: i ** x
def f():
return [create_lambda(i) for i in range(5)]
現(xiàn)在create_lambda()是一個(gè)新的作用域,它具有自己的本地i供lambda閉包引用。然后,每個(gè)lambda都有自己的閉包:
>>> L[0].__closure__[0] is L[1].__closure__[0]
False
閉包引用特定命名空間中的變量;每次您調(diào)用函數(shù)時(shí),都會(huì)創(chuàng)建一個(gè)新的本地名稱(chēng)空間,因此每個(gè)閉包都i在create_lambda與的其他調(diào)用不同的單獨(dú)名稱(chēng)空間中引用create_lambda。
添加回答
舉報(bào)