Pythonのローカル関数



python 関数内関数 利点 (3)

変数を非ローカルとして指定してクロージャの状態を保持する必要があります。したがって、定義は次のようにする必要があります

def outer():
a = 0
def inner():
    nonlocal a
    a += 1
inner()

次のPythonコードでは、 UnboundLocalErrorを取得しUnboundLocalError 。 私が理解しているように、ローカル関数は包含関数のローカル変数を共有しますが、ここではほとんどそうではありません。 この文脈では、 aは不変の値でaと認識してaますが、それは問題ではありません。

def outer():
    a = 0
    def inner():
        a += 1
    inner()
outer()

aの値が可変型でラップされている場合、 UnboundLocalError例外をUnboundLocalErrorないので、内部関数は親関数内のすべての参照のコピーを受け取ったように見えます。

誰かがここでその振る舞いを明確にすることができ、これに関する適切なPythonドキュメントを教えてくれますか?


私はあなたがこれを「変化の可能性」の問題と見なすのは正しいと信じています。 あなたが投稿したコードは "UnboundLocalError"をスローしますが、次のコードはそうではありません:

def outer():
    a = 0
    def inner():
        print a
    inner()
outer()

Pythonでは、内部スコープの外部スコープから変数の値を再割り当てすることはできません(キーワードglobalを使用していない限り、この場合は適用されません)。

このPython 2.6.2ドキュメントの "classes"ドキュメントの一番下のセクションを見てください:

9.2。 Pythonスコープと名前空間

[...]名前がグローバル宣言されている場合、すべての参照と割り当てはモジュールのグローバル名を含む中間スコープに直接移動します。 それ以外の場合は、最も内側のスコープの外にある変数はすべて読み取り専用です(そのような変数に書き込むと、最も内側のスコープに新しいローカル変数が作成され、同じ名前の外部変数は変更されません)。

"UnboundLocalError"はあなたの関数が実際に "a"という新しい変数を宣言してすぐに "+ ="演算をしようとしているためですが、 "a"にまだ値がないので失敗します。 (「a + = 1」を「a = a + 1」と表示し、「a」が未定義の場合は問題を見ることができます)。

一般的に、 "a"を変更したい場合、人が普通に回る方法は、変更可能な型を使用して "a"(リストや辞書など)を渡すことです。 あなたは変更可能なタイプの内容を使って "a"を変更することができます(この設定であなたのテストで気づいたでしょう)。

希望が助けてくれる!


変数を引数としてバインドしてみてください。

def outer():
    a = 0
    def inner(a=a):
        a += 1

    inner()

outer()

私は適切な文書を掘り下げようとします。

編集

内部関数が外部スコープに副作用を持たせたいので、リストのような可変データ型を使う必要があります。 整数と文字列は不変です。

def outer():
    a = [0]
    def inner():
        a[0] += 1
    inner()
    print a[0]
outer()




local