爲什麼以下兩個列表解析的輸出不同,即使f和lambda函數是相同的?Python:列表解析中的Lambda函數
f = lambda x: x*x
[f(x) for x in range(10)]
和
[lambda x: x*x for x in range(10)]
你要知道,這兩種類型(f)和式(拉姆達X:X * X)返還相同種類。
爲什麼以下兩個列表解析的輸出不同,即使f和lambda函數是相同的?Python:列表解析中的Lambda函數
f = lambda x: x*x
[f(x) for x in range(10)]
和
[lambda x: x*x for x in range(10)]
你要知道,這兩種類型(f)和式(拉姆達X:X * X)返還相同種類。
第一個創建一個lambda函數並調用它十次。
第二個不調用該函數。它創建10個不同的lambda函數。它將所有這些列入清單。爲了讓相當於你所需要的第一:
[(lambda x: x*x)(x) for x in range(10)]
或者更好的是:
[x*x for x in range(10)]
或'地圖(lambda x:x * x,範圍(10))',這可能是OP的意思首先。 – 2011-05-20 18:53:16
是的,lambda x:x * x ..(x)似乎是信條。 – staticor 2013-08-19 16:09:48
[lambda x:x * x在範圍內(10)] 基本上是haskell中的函數 – 2015-08-29 19:51:42
的最大區別在於,第一個例子中實際調用拉姆達f(x)
,而第二個例子沒有。
您的第一個示例相當於[(lambda x: x*x)(x) for x in range(10)]
,而第二個示例相當於[f for x in range(10)]
。
第一個
f = lambda x: x*x
[f(x) for x in range(10)]
運行f()
那麼它f(x)
爲每個值
第二個
[lambda x: x*x for x in range(10)]
在範圍內的每個值會運行中的每個值拉姆達該列表,因此它會生成所有這些功能。
人民給了很好的答案,但忘了提,我認爲最重要的部分: 在第二個例子中,列表理解的X
是不一樣的lambda
功能的X
,他們是完全無關的。 因此,第二個實施例實際上是相同的:
[Lambda X: X*X for I in range(10)]
上range(10)
內部迭代僅用於在列表生成器10個類似lambda函數(10個獨立的功能,但完全類似負責 - 返回每個輸入的功率2 )。
。另一方面,第一個例子中的作品完全不同,因爲重複的X做的結果進行交互,每個迭代的值是X*X
這樣的結果將是[0,1,4,9,16,25, 36, 49, 64 ,81]
這是一個重要的觀點。我在你的答案中提出了你的建議並詳細闡述了它。 – 2015-12-01 13:19:19
這個問題倒是很「着名」和「顯而易見的」Python語法的一部分發臭 - 優先,lambda或列表理解。
我不認爲OP的目的是生成一個從0到9的方塊列表。如果是這樣的話,我們可以給更多的解決方案:
squares = []
for x in range(10): squares.append(x*x)
但是這不是問題的關鍵。關鍵是W(hy)TF是否是這種模棱兩可的表達方式,所以反直覺?最後我對你有一個愚蠢的例子,所以不要太早拒絕我的回答(我在面試時曾經這樣做過)。
因此,OP的理解返回lambda表達式的列表:
[(lambda x: x*x) for x in range(10)]
這當然只是10個不同平方函數的副本,請參閱:
>>> [lambda x: x*x for _ in range(3)]
[<function <lambda> at 0x00000000023AD438>, <function <lambda> at 0x00000000023AD4A8>, <function <lambda> at 0x00000000023AD3C8>]
注意的lambda的內存地址 - 它們都是不同的!
你當然可以有更多的 「最佳」(哈哈)版本的表情:
>>> [lambda x: x*x] * 3
[<function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>]
看到了嗎? 3次相同 lambda。
請注意,我用_
作爲for
變量。它與lambda
中的x
無關(它在詞法上被掩蓋了!)。得到它?
我要離開了討論,爲什麼語法優先不是這樣,它所有的意思是:
[lambda x: (x*x for x in range(10))]
這可能是:[[0, 1, 4, ..., 81]]
,或[(0, 1, 4, ..., 81)]
,或這是我覺得最合乎邏輯的,這將是1個元素的list
- 一個generator
返回值。情況並非如此,這種語言不適用於這種方式。
但什麼,如果...
,如果你不掩蓋for
變量,並在你的lambda
的使用它什麼???
好吧,那麼廢話發生。看看這個:
[lambda x: x * i for i in range(4)]
這意味着課程:
[(lambda x: x * i) for i in range(4)]
不過,這並不意味着:
[(lambda x: x * 0), (lambda x: x * 1), ... (lambda x: x * 3)]
這僅僅是瘋了!
列表理解的lambda表達式是在這個理解的範圍封閉。一個詞彙封閉,所以他們通過參考參考i
,而不是它的價值,當他們被評價過!
所以,這個表達式:
[(lambda x: x * i) for i in range(4)]
大致等同於:
[(lambda x: x * 3), (lambda x: x * 3), ... (lambda x: x * 3)]
我敢肯定,我們可以看到更多的在這裏使用一個Python反編譯器(我指的是例如在dis
模塊),但對於Python-VM不可知的討論,這已經足夠了。 這麼多的求職面試問題。
現在,如何製作乘法器lambda的list
,它真的乘以連續的整數?那麼,同樣接受的答案,我們需要通過包裝它在另一個lambda
,這是越來越稱爲內列表解析表達式打破直接領帶i
:
前:
>>> a = [(lambda x: x * i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
2
後:
>>> a = [(lambda y: (lambda x: y * x))(i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
1
(我不得不外的λ可變也= i
,但我決定,這是更清晰的溶液 - 我介紹y
,這樣我們都可以看到哪個女巫是哪個)。
這是一個殘酷而不尋常的求職面試問題。 – szeitlin 2015-12-11 17:49:37
我的頭燒焦閱讀你的答案! – Valilutzik 2016-09-25 17:57:51
如果我的同事沒有問,我可能永遠不會搜索這個答案 – piggybox 2016-11-10 01:33:43
其他的答案是正確的,但如果你試圖使功能列表,每一個不同的參數,可以執行後,下面的代碼將做到這一點:
import functools
a = [functools.partial(lambda x: x*x, x) for x in range(10)]
b = []
for i in a:
b.append(i())
In [26]: b
Out[26]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
雖然例子是人爲的,我認爲它是有用的時候想的功能的列表,每個打印不同的東西,即
import functools
a = [functools.partial(lambda x: print(x), x) for x in range(10)]
for i in a:
i()
'[拉姆達X:X * X爲在範圍X(10)]'快於第一個,因爲它沒有調用外部循環函數,f代表eatedly。 – riza 2011-05-20 18:50:47
@Selinap:...不,相反,您要通過循環創建一個品牌嶄新的功能。 ...和創建這個新功能的開銷,然後調用速度稍慢(無論如何我的系統上)。 – Gerrat 2011-05-20 19:00:12
@Gerrat:即使有開銷,它仍然更快。但是,當然'[x * x在範圍內(10)]'更好。 – riza 2011-05-20 19:13:23