2016-12-06 6 views
3

をスコープ変数を囲むが、私はこの単純なコードを書きましたこのための が、私はループ変数は、最後のループ反復に持っていた値を見つけることが期待されるが、私は私のリストをチェックしたとき、私は以下を参照してください:、それらはすべて実質的に同じ値を覚えてPythonはラムダ関数と

>>> mylist[0](0) 
1 
>>> mylist[0](1) 
4 
>>> mylist[0](2) 
16 
>>> 
私はとても混乱している

は、なぜ私のコードは、ループの値の最後を保持しないのですか?私は明示的にこのようなデフォルト引数でスコープ値を囲む保持する必要はありません理由:事前

答えて

3

iが時間の経過と共に複数の値をとっても、の変数,iが有効です。ループ中にiの内容が変更されています。しかし、クロージャーは値ではなく変数を取り込みます。あなたがそれを呼び出すまでラムダ内で評価されるものはありません。関数を呼び出すときには、現在の値のiにアクセスします。これは最後のものです。機能がある

Pythonのデフォルト引数は、関数が定義されたときに一度だけ評価されている、いないたび:i=iが問題を解決する理由については

が、これは The Hitchhiker's guide to Python共通落とし穴)の例で説明されますいわゆる(Rubyのように)呼び出されました。つまり、変更可能なデフォルトの引数を使用してそれを変更すると、その関数への今後のすべての呼び出しに対してそのオブジェクトを変更してしまいます。

だから、あなたが作成し(とすぐ外のようなiを命名することが起こる)クロージャの内部で発生する各新たな結合が閉鎖を作成するときに、デフォルト値が計算されています。したがって、クロージャが呼び出されたときにすぐに使用できるように、適切な値が設定されています。

3

まずにおける

L.append(lambda x, i=i: i ** x) 

おかげで、それらはすべて使用しているため、リスト内のすべての5つの機能は、同一であることを観察します最終の値i内側からmakelist

iは、しかし、lambda式が評価されたときに作成閉鎖の一部です。それはあなたがmakelistからあなたコール機能、これは関数のいずれかに影響を与えない範囲でiに新しい値を割り当てるとすることを意味します。それらは、グローバルスコープからではなく、クロージャの結果として関数に付加された名前空間からiの値を検索します。