lambda
関数は、変数i
を周囲のスコープから取得します。 this questionに記載されているように、その範囲は理解の範囲である。
ループはジェネレータのアイテムを一度に1つずつ繰り返し、ジェネレータを進める前にループを呼び出します。最初の関数を取得すると、ジェネレータは、i
が0の状態で中断されているので、関数が参照する値になります。ジェネレータを進めると、i
が1に設定され、その値を取得する関数が得られます。ジェネレータは、次の機能に進むまで、i
を変更するのを待ちます。
リストの理解では、すぐにすべての関数を取得します。しかし、すべてはまだ理解範囲内の同じ変数i
を参照しています。リストの理解はすぐに終了するので、i
は4つまですべての機能を使用する機会を得ます。
どちらの場合でも、ラムダは理解範囲内の変数を参照しています。ジェネレータの理解では、以前の関数を呼び出した後でなければ、この変数は進まないということだけです。あなたが最初の関数を保存する場合は、リスト・理解のケースと同様の挙動を見ることができますが、再び発電進出後までそれを呼び出すことはありません:
def create_funcs():
return (lambda: i for i in range(5))
gen = create_funcs()
f1 = next(gen)
f2 = next(gen)
print(f1())
print(f2())
出力があるので
1
1
です私は発電機を進めました、i
は1なので、f1
とf2
の両方が呼び出されたときにその値を参照してください。 for f in list(create_funcs())
を実行しても同じことが分かります。リストの理解が終わるまでジェネレータを最後まで強制的に移動させます。
@BrenBarn:申し訳ありませんが、他の質問の答えが私のものであるかどうか分かりません。 –
特に[この回答](http://stackoverflow.com/questions/4575698/python-list-comprehension-overridingvalue/4575866#4575866)をご覧ください。 – BrenBarn
@BrenBarn:OKですが、私はPython3.5を使用しています。なぜ漏れてしまいますか? –