python 閉包問題

問題:下面這段代碼的輸出結果將是什麼?

def multipliers():
	return [lambda x: i * x for i in range(4)]

print([m(2) for m in multipliers()])

答:上面代碼輸出的結果是 [6, 6, 6, 6](不是我們想的 [0, 2, 4, 6])。
上述問題產生的原因是 Python 閉包的延遲綁定。這意味着內部函數被調用時,參數的值在閉包內進行查找。因此,當任何由 multipliers()返回的函數被調用時,i 的值將在附近的範圍進行查找。那時,不管返回的函數是否被調用,for 循環已經完成,i 被賦予了最終的值 3。因此,每次返回的函數乘以傳遞過來的值 3,因爲上段代碼傳過來的值是 2,它們最終返回的都是 6 即 (3*2)。

問題:什麼是閉包?
在函數內部再定義一個函數,並且這個函數用到了外邊函數的變量,那麼將這個函數以及用到的一些變量稱之爲 閉包。

問題:如何修改上面的 multipliers 的定義從而產生想要的結果?
一種解決方法就是用 Python 生成器。

def multipliers_1():
	for i in range(4):
		yield lambda x: i * x

print([m(2) for m in multipliers_1()])

另外一個解決方案就是創造一個閉包,利用默認參數立即綁定。

def multipliers_2():
	return [lambda x, i=i: i * x for i in range(4)]

print([m(2) for m in multipliers_2()])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章