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を与えられる.したがって、各返される関数には、上段コードから渡される値が2であり、最終的に返される値が6である(3*2)ため、渡される値3が乗算される.
質問:閉鎖とは何ですか.関数の内部にもう1つの関数を定義し、この関数が外部関数の変数を使用すると、この関数と使用されるいくつかの変数を閉パケットと呼ぶ.
質問:上記のmultipliersの定義をどのように修正して所望の結果を生成しますか?1つの解決策はPythonジェネレータを使うことです.
def multipliers_1():
	for i in range(4):
		yield lambda x: i * x

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

もう1つの解決策は、デフォルトのパラメータを使用してすぐにバインドされる閉パッケージを作成することです.
def multipliers_2():
	return [lambda x, i=i: i * x for i in range(4)]

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