第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

(lambda)函數(shù)閉包捕獲了什么?

(lambda)函數(shù)閉包捕獲了什么?

最近我開始玩Python,我遇到了一些特殊的閉包方式。請考慮以下代碼:adders=[0,1,2,3]for i in [0,1,2,3]:    adders[i]=lambda a: i+aprint adders[1](3)它構(gòu)建了一個簡單的函數(shù)數(shù)組,它接受單個輸入并返回由數(shù)字添加的輸入。函數(shù)在for循環(huán)中構(gòu)造,迭代器i從中循環(huán)0到3。對于這些數(shù)字中的每一個,lambda都會創(chuàng)建一個函數(shù)i,該函數(shù)捕獲并將其添加到函數(shù)的輸入中。最后一行將第二個lambda函數(shù)3作為參數(shù)調(diào)用。令我驚訝的是輸出結(jié)果是6。我期待一個4。我的理由是:在Python中,一切都是一個對象,因此每個變量都是指向它的指針。在創(chuàng)建lambda閉包時i,我希望它存儲一個指向當(dāng)前指向的整數(shù)對象的指針i。這意味著當(dāng)i分配一個新的整數(shù)對象時,它不應(yīng)該影響先前創(chuàng)建的閉包。遺憾的是,adders在調(diào)試器中檢查數(shù)組表明它確實存在。所有的lambda功能指的最后一個值i,3,這將導(dǎo)致adders[1](3)返回6。這讓我想知道以下內(nèi)容:閉包捕獲的內(nèi)容是什么?什么是最優(yōu)雅的方式來說服lambda函數(shù)以更改其值i時不會受到影響的方式捕獲當(dāng)前i值?
查看完整描述

4 回答

?
慕后森

TA貢獻(xiàn)1802條經(jīng)驗 獲得超5個贊

您可以使用具有默認(rèn)值的參數(shù)強(qiáng)制捕獲變量:


>>> 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

我們的想法是聲明一個參數(shù)(巧妙地命名i)并給它一個你想要捕獲的變量的默認(rèn)值(值  i)


查看完整回答
反對 回復(fù) 2019-05-27
?
慕斯王

TA貢獻(xiàn)1864條經(jīng)驗 獲得超2個贊

為了完整性,您對第二個問題的另一個答案是:您可以在functools模塊中使用partial。

通過從運(yùn)營商導(dǎo)入add,Chris Lutz提出的示例變?yōu)椋?/p>

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)


查看完整回答
反對 回復(fù) 2019-05-27
?
qq_笑_17

TA貢獻(xiàn)1818條經(jīng)驗 獲得超7個贊

請考慮以下代碼:

x = "foo"def print_x():
    print x

x = "bar"print_x() # Outputs "bar"

我想大多數(shù)人都不會發(fā)現(xiàn)這種混亂。這是預(yù)期的行為。

那么,為什么人們認(rèn)為它在循環(huán)中完成時會有所不同?我知道我自己犯了這個錯誤,但我不知道為什么。這是循環(huán)?或者也許是lambda?

畢竟,循環(huán)只是一個較短的版本:

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


查看完整回答
反對 回復(fù) 2019-05-27
?
慕運(yùn)維8079593

TA貢獻(xiàn)1876條經(jīng)驗 獲得超5個贊

你的第二個問題已得到解答,但至于你的第一個問題:

封閉捕獲到底是什么?

Python中的范圍是動態(tài)的和詞匯的。閉包將始終記住變量的名稱和范圍,而不是它指向的對象。由于示例中的所有函數(shù)都在同一作用域中創(chuàng)建并使用相同的變量名,因此它們始終引用相同的變量。

編輯:關(guān)于如何克服這個問題的另一個問題,有兩種方法可以想到:

  1. 最簡潔但不嚴(yán)格等同的方式是Adrien Plisson推薦的方式。使用額外參數(shù)創(chuàng)建lambda,并將額外參數(shù)的默認(rèn)值設(shè)置為要保留的對象。

  2. 每次創(chuàng)建lambda時,創(chuàng)建一個新范圍會更冗長但更少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

    這里的范圍是使用一個新函數(shù)(lambda,為簡潔起見)創(chuàng)建的,它綁定了它的參數(shù),并傳遞你想要綁定的值作為參數(shù)。但是,在實際代碼中,您很可能會使用普通函數(shù)而不是lambda來創(chuàng)建新范圍:

    def createAdder(x):
        return lambda y: y + x
    adders = [createAdder(i) for i in range(4)]


查看完整回答
反對 回復(fù) 2019-05-27
  • 4 回答
  • 0 關(guān)注
  • 1342 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號