python lambda在列表推導式中的閉包問題

2021-10-20 00:13:20 字數 1698 閱讀 4594

給出以下**的pirnt結果

li =

[lambda

: x for x in

range(10

)]ret = li[0]

()print

(ret)

答案是9,出乎意料的是li內的所有匿名函式的結果都是9。

python 閉包的後期繫結導致的 late binding,這意味著在閉包中的變數是在內部函式被呼叫的時候被查詢。所以結果是,當任何 li 內的匿名函式被呼叫時,x的值是在它被呼叫時的周圍作用域中查詢,無論哪個lambda函式被呼叫,for 迴圈都已經完成了,x 最後的值是9,因此,每個lambda函式返回的值都是 9。

我們從下圖中能更好的理解這個列表推導式

整體上li是乙個[ *** for x in range(10) ]列表推導式,重點是這個***又是乙個匿名函式表示式lambda :x。 這個函式在呼叫時會返回x的值。

因此li表示式的第一步是生成了10個匿名表示式, 在這一步迴圈是已經結束了的, 迴圈的目的是生成10個匿名函式。如圖:

但是匿名函式的內部變數又使用了迴圈產生的變數x, x與匿名函式形成了乙個閉包。 迴圈結束x的值只能是9,所以在每個函式呼叫時,結果都是9。

通過以下等同的**,我們可以明確的看出閉包的形成:

li = list()

for x in range(10):

def test():

return x

此外,我們可以通過變數賦值的方式,儲存每次迴圈時x的值,就可以得到正確的結果了:

什麼是 lambda?

匿名函式表示式,目的是簡略函式的定義,使用簡單的一行**就實現乙個函式功能。如果超過2行**,就不要使用lambda了。lambda表示式的意義就是簡潔明瞭。過於複雜不利於**的可讀性。

無引數的lambda, 上例就是乙個無參的匿名函式。

帶引數的lambda

lambda x: x+1 這個匿名函式的功能是返回每次傳入的引數+1,如下圖:

帶表示式的lambda

上例li = [lambda j=x: j for x in range(10)]就是乙個帶有表示式的匿名函式。但是匿名函式不要過於複雜化。大多時候太複雜話不利於**的可讀性,同時又容易出現不易察覺bug。所以炫技要適當,不然就容易翻車了,還是老老實實寫簡單易懂的**吧。

python lambda函式基礎

本文,我們學習python lambda函式。首先,看一下python lambda函式的語法,如下 f lambda parameter1,parameter2,expression lambda語句中,冒號前是引數,可以有0個或多個,用逗號隔開,冒號右邊是返回值。lambda語句構建的其實是乙個...

python lambda匿名函式

lambda定義乙個匿名函式 lambda只是乙個表示式,函式體比def簡單很多,很多時候定義def,然後寫乙個函式太麻煩,這時候就可以用lambda定義乙個匿名函式。lambda的主體是乙個表示式,而不是乙個 塊。僅僅能在lambda表示式中封裝有限的邏輯進去。參考鏈結 lambda的特性 乙個語...

python lambda 匿名函式

語法 lambda 引數 表示式 接受引數,執行表示式,返回結果 示例 乙個lambda函式,把引數加10,然後返回結果 x lambda a a 10print x 5 lambda函式可以接受任意數量的引數 示例 乙個lambda函式,將引數a與引數b相乘,然後返回結果 x lambda a,b...