2017-09-01 7 views
0

最初に(技術的なコーディングのバックグラウンドなしに)関数を実行すると、私はこのようになる概念を理解することができません。Mark Lutzが私をちょっと混乱させます

単純な関数工場:

対話プロンプトで入力した次の機能を考慮し、簡単な用語でこれを説明するためには:

>>> def maker(N): 
...  def action(X): # Make and return action 
...   return X ** N # action retains N from enclosing scope 
...  return action 

これは単に、ネストされたを生成して返す外側の関数を定義それを実行せずにアクションを返すだけです。私たちは、外側の関数を呼び出す場合:

>>> f = maker(2) # Pass 2 to argument N 
>>> f 

.action 0x0000000002A4A158で>

私たちが戻って取得することは生成されたネストされた関数、ネストされたデフ実行作成したものへの参照です。

私たちは、ネストされた関数、つまり、メーカー内のactionと呼ばれる関数を呼び出します。言い換えれば、私たちはメーカーが作成し戻したネストされた関数を呼び出しています。 おそらく、この中でもっとも珍しい部分は、ネストされた関数が、私たちがアクションを呼んだときに返されて終了したとしても、メーカーの変数Nの値である整数2を覚えているということです。実際には、囲むローカルスコープからのNは、生成されたアクションに付随する状態情報として保持されるため、後で呼び出されるときにその引数の二乗を元に戻す理由です。同様に重要なことに、外部関数を再び呼び出すと、異なる状態情報が付加された新しい入れ子関数が返されます。まさにここに何が起こる

>>> g = maker(3) # g remembers 3, f remembers 2 
>>> g(4) # 4 ** 3 
64 
>>> f(4) # 4 ** 2 

を:それは私たちが以前のように新しい関数を呼び出すとき立方代わりに乗引数が、元の静止正方形を取得し、です。私が理解できる視点を与えてください。

+1

あなたの質問のタイトルを改善しようとしてください:今、質問がどんなものかについて非常に不明です。 –

+0

あなたの説明は正しいです、返された関数で少しの状態が保持されています。これは字句クロージャと呼ばれ、関数が作成されるときに字句スコープ内の変数を含む関数であり、それらの変数は「閉じられ」、関数と共に保存されます。私は本当にあなたの質問が最終的にはどのように実装されているか尋ねているのですか? – Ukko

+0

も参照してください。https://stackoverflow.com/q/21959985/124319閉包によってキャプチャされている変数を変更する* – coredump

答えて

1

actionは、クロージャと呼ばれるものです。これは、関数本体と、いわゆるフリーの変数の値を含む環境とともに、関数オブジェクトの組み合わせであり、関数の本体で使用される非ローカル名です。この場合

actionactionが定義されているmakerへの呼び出しから「継承」されnの値を含む環境上の閉鎖、です。 makerへの各呼び出しでは、という名前の新しい関数オブジェクトがと定義されています。 makerへの呼び出しによって返されたクロージャは、この新しい関数と、に渡されたnの値とで構成されます。

実際には、関数とクロージャの違いはほとんどありません。非ローカル名の一部がグローバルまたは呼び出しスコープではなく、囲まれた環境から値を受け取ることを除いて、関数とまったく同じように動作します。

関連する問題