Python 2.x には、読み取り/書き込みで変数をキャプチャすることを許可しない構文制限があります。
その理由は、変数が関数で割り当てられた場合、2 つの可能性しかないからです。
- 変数はグローバルであり、そのように宣言されています
global x
- 変数は関数のローカルです
より具体的には、変数が囲んでいる関数スコープのローカルであることは除外されます
nonlocal
これは、Python 3.x で宣言が追加されて置き換えられました。コードを次のように変更することで、Python 3 で期待どおりに動作します。
def make_adder_and_setter(x):
def setter(n):
nonlocal x
x = n
return (lambda y: x + y, setter)
Python 2.x ランタイムは、バイトコード レベルでクローズド オーバー変数の読み書きを処理できますが、制限はコンパイラが受け入れる構文にあります。
このビデオの最後で、読み取り/書き込みのキャプチャ状態で加算器クロージャを作成する Python バイトコードを直接生成する Lisp コンパイラを見ることができます。コンパイラは、Python 2.x、Python 3.x、または PyPy のバイトコードを生成できます。
Python 2.xa でクローズド オーバーの可変状態が必要な場合は、リストを使用するのがコツです。
def make_adder_and_setter(x):
x = [x]
def setter(n):
x[0] = n
return (lambda y: x[0] + y, setter)