スコープ変数をラムダ関数で囲むPython

AleMal

私はこの簡単なコードを書きました:

def makelist():
  L = []
  for i in range(5):
    L.append(lambda x: i**x)
  return L

わかりました、今私は電話します

mylist = makelist()

ネストされた関数が後で呼び出されたときに囲んでいるスコープ変数が検索されるため、それらはすべて事実上同じ値を記憶します。このため、最後のループ反復でループ変数が持っていた値を見つけることを期待していましたが、リストを確認するとそうですか:

>>> mylist[0](0)
1
>>> mylist[0](1)
4
>>> mylist[0](2)
16
>>> 

私はとても混乱しています、なぜ私のコードは最後のforループ値を保持しないのですか?次のようなデフォルトの引数を使用して、囲んでいるスコープ値を明示的に保持する必要がないのはなぜですか。

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

前もって感謝します

コアダンプ

にもかかわらずi効果的に1つのだけで、時間をかけて複数の値をとる変数はiの内容はiループ中に変更されています。ただし、クロージャは値ではなく変数をキャプチャします。ラムダを呼び出すまで、ラムダ内では何も評価されません。関数を呼び出すときに、現在の値にアクセスしますi。これはたまたま最後の値です

なぜi=i問題解決するのかについては、これは、たとえば、ヒッチハイカーのPythonガイドCommon Gotchas)で説明されています

Pythonのデフォルトの引数は、関数が呼び出されるたびにではなく、関数が定義されたときに1回評価されます(たとえば、Rubyのように)。つまり、変更可能なデフォルト引数を使用して変更すると、関数への今後のすべての呼び出しでもそのオブジェクトが変更されます。

したがって、作成したクロージャーの内部で発生する(そしてi、外部のバインディングと同じように名前が付けられる)新しいバインディングには、クロージャーの作成時にデフォルト値が計算されます。その結果、「正しい」値が設定され、クロージャが呼び出されたときにすぐに使用できるようになります。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

ラムダ関数の外部スコープ変数

分類Dev

ラムダでスコープを囲むことで定義された配列を変更する

分類Dev

ラムダ関数を変数に割り当てるときに、ラムダ関数を角かっこで囲む必要があるのはなぜですか?

分類Dev

高階ラムダ関数の可変スコープ

分類Dev

スコープを囲む変数を使用した関数のノード配列

分類Dev

forループ内で変数を囲む

分類Dev

Python 3例外は、不明な理由でスコープを囲む変数を削除します

分類Dev

Java:Javaがラムダ式のスコープを囲む際にローカル変数を自動的に「ファイナライズ」できないのはなぜですか?

分類Dev

範囲関数Pythonでカスタムオーダーを使用する

分類Dev

美しいスープでラムダ関数を使用する

分類Dev

美しいスープでラムダ関数を使用する

分類Dev

メソッドが終了した後、ラムダ式がスコープ変数値の囲みを保持するのはなぜですか?

分類Dev

外部変数をラムダ関数のスコープに渡すにはどうすればよいですか?

分類Dev

Pythonで囲んでいるスコープ変数を返します

分類Dev

Groovyメソッドはスコープを囲む変数にアクセスできません

分類Dev

c ++ 11以下のラムダ関数のスコープは何ですか

分類Dev

C ++ 11のラムダ関数のスコープは何ですか(委任)

分類Dev

Pythonを囲む関数

分類Dev

ラムダ関数でコピーによってキャプチャされた変数の値を変更できないのはなぜですか?

分類Dev

関数、すなわちラムダを取り込むpygameでスプライトを更新する方法は?

分類Dev

関数、すなわちラムダを取り込むpygameでスプライトを更新する方法は?

分類Dev

関数パラメーター内の変数を中括弧で囲むとはどういう意味ですか

分類Dev

キャプチャリストにない限り、囲んでいる関数のローカル変数をラムダ本体で参照することはできません

分類Dev

関数内でクラスを作成し、それを含む関数のスコープで定義された関数にアクセスする

分類Dev

ラムダ関数を含むコールスタックが与えられた場合、そのソースをどのように決定できますか?

分類Dev

関数内で外部スコープ変数を定義する

分類Dev

ラムダ計算/ haskellの変数のスコープ

分類Dev

Haskell:ラムダ関数-エラー-スコープをエスケープする

分類Dev

ラムダ関数(ラムダのキャプチャを含む)をstd :: functionオブジェクトに変換するためのテンプレート

Related 関連記事

  1. 1

    ラムダ関数の外部スコープ変数

  2. 2

    ラムダでスコープを囲むことで定義された配列を変更する

  3. 3

    ラムダ関数を変数に割り当てるときに、ラムダ関数を角かっこで囲む必要があるのはなぜですか?

  4. 4

    高階ラムダ関数の可変スコープ

  5. 5

    スコープを囲む変数を使用した関数のノード配列

  6. 6

    forループ内で変数を囲む

  7. 7

    Python 3例外は、不明な理由でスコープを囲む変数を削除します

  8. 8

    Java:Javaがラムダ式のスコープを囲む際にローカル変数を自動的に「ファイナライズ」できないのはなぜですか?

  9. 9

    範囲関数Pythonでカスタムオーダーを使用する

  10. 10

    美しいスープでラムダ関数を使用する

  11. 11

    美しいスープでラムダ関数を使用する

  12. 12

    メソッドが終了した後、ラムダ式がスコープ変数値の囲みを保持するのはなぜですか?

  13. 13

    外部変数をラムダ関数のスコープに渡すにはどうすればよいですか?

  14. 14

    Pythonで囲んでいるスコープ変数を返します

  15. 15

    Groovyメソッドはスコープを囲む変数にアクセスできません

  16. 16

    c ++ 11以下のラムダ関数のスコープは何ですか

  17. 17

    C ++ 11のラムダ関数のスコープは何ですか(委任)

  18. 18

    Pythonを囲む関数

  19. 19

    ラムダ関数でコピーによってキャプチャされた変数の値を変更できないのはなぜですか?

  20. 20

    関数、すなわちラムダを取り込むpygameでスプライトを更新する方法は?

  21. 21

    関数、すなわちラムダを取り込むpygameでスプライトを更新する方法は?

  22. 22

    関数パラメーター内の変数を中括弧で囲むとはどういう意味ですか

  23. 23

    キャプチャリストにない限り、囲んでいる関数のローカル変数をラムダ本体で参照することはできません

  24. 24

    関数内でクラスを作成し、それを含む関数のスコープで定義された関数にアクセスする

  25. 25

    ラムダ関数を含むコールスタックが与えられた場合、そのソースをどのように決定できますか?

  26. 26

    関数内で外部スコープ変数を定義する

  27. 27

    ラムダ計算/ haskellの変数のスコープ

  28. 28

    Haskell:ラムダ関数-エラー-スコープをエスケープする

  29. 29

    ラムダ関数(ラムダのキャプチャを含む)をstd :: functionオブジェクトに変換するためのテンプレート

ホットタグ

アーカイブ