(ラムダ)関数クロージャは何をキャプチャしますか?
最近、私はPythonをいじり始めましたが、クロージャーが機能する方法に変わったものを見つけました。次のコードを検討してください。 adders=[0,1,2,3] for i in [0,1,2,3]: adders[i]=lambda a: i+a print adders[1](3) これは、単一の入力を受け取り、その入力を数値で追加した関数を返す単純な配列を作成します。関数はforループで構築され、イテレータiはから0まで実行され3ます。これらの数値のそれぞれに対して、lambda関数を作成iして関数の入力に追加する関数が作成されます。最後の行は、パラメーターとして2番目のlambda関数を呼び出し3ます。驚いたことに、出力はでした6。 期待していました4。私の推論は:Pythonではすべてがオブジェクトであり、したがってすべての変数はオブジェクトへのポインターとして不可欠です。のlambdaクロージャーを作成するときにi、が現在ポイントしている整数オブジェクトへのポインターを格納することを期待していましたi。つまりi、新しい整数オブジェクトが割り当てられた場合、以前に作成されたクロージャーには影響しません。悲しいことに、addersデバッガー内で配列を検査すると、配列がそうであることがわかります。すべてlambdaの関数は最後の値を参照してくださいi、3で、その結果adders[1](3)を返します6。 次のことについて不思議に思います: クロージャは正確に何をキャプチャしますか? lambda現在の値をキャプチャして、値を変更してiも影響を受けないように関数を説得する最もエレガントな方法は何iですか?