21

Python 3.3.1 では、次のように動作します。

i = 76

def A():
    global i
    i += 10

print(i) # 76
A()
print(i) # 86

これも機能します:

def enclosing_function():
    i = 76
    def A():
        nonlocal i
        i += 10

    print(i) # 76
    A()
    print(i) # 86

enclosing_function()

しかし、これはうまくいきません:

i = 76
def A():
    nonlocal i # "SyntaxError: no binding for nonlocal 'i' found"
    i += 10

print(i)
A()
print(i)

nonlocalキーワード状態のドキュメント(強調を追加):

非ローカル ステートメントにより、リストされた識別子は、最も近い外側のスコープ内の以前にバインドされた変数を参照します。

3 番目の例では、「最も近いエンクロージング スコープ」がたまたまグローバル スコープになっています。では、なぜうまくいかないのでしょうか。

このビットを読んでください

ドキュメントが次のように続くことに気付きました(強調を追加):

[ ] ステートメントにより、カプセル化されたコードは、グローバル (モジュール) スコープ以外nonlocalのローカル スコープ外の変数を再バインドできます。

しかし、厳密に言えば、これは、3 番目の例で行っていることがうまくいかないという意味ではありません。

4

4 に答える 4

10

名前の検索順序は、LEGB、つまりローカル、エンクロージング、グローバル、ビルトインです。したがって、グローバル スコープは外側のスコープではありません。

編集

ドキュメントから:

nonlocal ステートメントにより、リストされた識別子は、最も近い外側のスコープで以前にバインドされた変数を参照します。バインドの既定の動作では、最初にローカルの名前空間を検索するため、これは重要です。このステートメントにより、カプセル化されたコードは、グローバル (モジュール) スコープ以外のローカル スコープ外の変数を再バインドできます。

于 2013-06-01T14:20:57.070 に答える
4

モジュールのスコープがグローバルと見なされ、それを囲むものと見なされないのはなぜですか? それはまだ他のモジュールに対してグローバルではありません (そうでない限りfrom module import *) ですね。

moduleの名前空間に名前を入れた場合。moduleつまり、Python プロセス全体でグローバルです。

一般に、アプリケーションで使用する変更可能なグローバルはできるだけ少なくする必要があります。グローバルが悪い理由を参照してください。:

  • 非局所性
  • アクセス制御または制約チェックなし
  • 暗黙的な結合
  • 同時実行の問題
  • 名前空間の汚染
  • 検査と監禁

したがってnonlocal、誤ってグローバルを作成することを許可するのは良くありません。グローバル変数を変更したい場合。globalキーワードを直接使用できます。

  • global最も破壊的です: プログラム内の任意の場所でのモジュールのすべての使用に影響を与える可能性があります
  • nonlocal破壊的ではありません: outer() 関数のスコープによって制限されます (バインディングはコンパイル時にチェックされます)
  • 宣言なし (ローカル変数) は最も破壊的なオプションです: inner() 関数のスコープによって制限されます

PEP: 3104 Access to Names in Outer Scopesnonlocalで歴史と動機について読むことができます。

于 2013-06-02T14:02:24.930 に答える
2

答えは、グローバル スコープは何も囲んでいないということです。つまり、すべてに対してグローバルです。globalそんな時にキーワードを使います。

于 2013-06-01T14:18:22.100 に答える