418

Pythonnonlocalステートメントは何をしますか(Python 3.0以降)?

Pythonの公式Webサイトにはドキュメントがなく、help("nonlocal")機能しません。

4

9 に答える 9

580

を使用せずにこれを比較しnonlocalます。

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

これには、 を使用しますnonlocal。ここでinner()xouter()ですx:

x = 0
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

を使用すると、適切な「グローバル」値にglobalバインドされます。x

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2
于 2009-08-11T17:53:30.780 に答える
108

つまり、外側の (ただしグローバルではない) スコープの変数に値を割り当てることができます。詳細についてはPEP 3104を参照してください。

于 2009-08-11T17:40:52.477 に答える
47

「python nonlocal」をグーグルで検索すると、ステートメントの背後にある構文と理由を完全に説明する提案、 PEP 3104が見つかりました。globalつまり、関数に対してグローバルでもローカルでもない変数を参照するために使用されることを除いて、ステートメントとまったく同じように機能します。

これで何ができるかの簡単な例を次に示します。これを使用するようにカウンター ジェネレーターを書き直して、クロージャーを使用する言語のイディオムのように見せることができます。

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

明らかに、これをジェネレーターとして次のように書くことができます。

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

しかし、これは完全に慣用的な python ですが、最初のバージョンは初心者にとってはもう少し明白であるように思われます。返された関数を呼び出してジェネレーターを適切に使用することは、よくある混乱のポイントです。最初のバージョンは明示的に関数を返します。

于 2009-08-11T17:50:45.793 に答える
22

@ooboo:

これは、ソースコードの参照ポイントに「最も近い」ものを取ります。これは「レキシカルスコープ」と呼ばれ、40年以上前から標準となっています。

Pythonのクラスメンバーは、実際にはと呼ばれる辞書__dict__にあり、字句スコープで到達することはありません。

指定せずに実行するnonlocalx = 7、新しいローカル変数「x」が作成されます。を指定するnonlocalと、「最も近い」「x」が検索され、それに割り当てられます。指定nonlocalして「x」がない場合は、エラーメッセージが表示されます。

キーワードglobalは、最も外側の「x」を除いて他のすべての「x」を喜んで無視するので、私にはいつも奇妙に見えました。変。

于 2010-12-05T13:30:02.083 に答える
15

help('nonlocal')nonlocalステートメント


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

このnonlocalステートメントにより、リストされたIDは、最も近い囲みスコープ内の以前にバインドされた変数を参照します。バインディングのデフォルトの動作は最初にローカル名前空間を検索することであるため、これは重要です。このステートメントを使用すると、カプセル化されたコードで、グローバル(モジュール)スコープ以外のローカルスコープ外の変数を再バインドできます。

ステートメントにリストされている名前は、nonlocalステートメントにリストされている名前とは異なり global、囲んでいるスコープ内の既存のバインディングを参照する必要があります(新しいバインディングを作成するスコープを明確に決定することはできません)。

ステートメントにリストされている名前nonlocalは、ローカルスコープ内の既存のバインディングと衝突してはなりません。

参照:

PEP3104-外部スコープの名前へのアクセスステートメント
の仕様。nonlocal

関連するヘルプトピック:グローバル、NAMESPACES

出典:Python言語リファレンス

于 2011-08-04T11:01:39.580 に答える
3

「非ローカル」ステートメントに関する私の個人的な理解 (そして、私は Python とプログラミング全般に慣れていないので失礼します) は、「非ローカル」は、コード自体ではなく、反復関数内でグローバル機能を使用する方法であるということです。 . 必要に応じて、関数間の Global ステートメント。

于 2011-08-04T10:25:00.040 に答える
3
a = 0    #1. global variable with respect to every function in program

def f():
    a = 0          #2. nonlocal with respect to function g
    def g():
        nonlocal a
        a=a+1
        print("The value of 'a' using nonlocal is ", a)
    def h():
        global a               #3. using global variable
        a=a+5
        print("The value of a using global is ", a)
    def i():
        a = 0              #4. variable separated from all others
        print("The value of 'a' inside a function is ", a)

    g()
    h()
    i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)
于 2015-05-06T13:11:20.783 に答える
0

「非ローカル」内部関数 (つまり、ネストされた内部関数) を使用すると、外部親関数の特定の変数に対する読み取りと「書き込み」許可を取得できます。また、非ローカルは内部関数内でのみ使用できます。例:

a = 10
def Outer(msg):
    a = 20
    b = 30
    def Inner():
        c = 50
        d = 60
        print("MU LCL =",locals())
        nonlocal a
        a = 100
        ans = a+c
        print("Hello from Inner",ans)       
        print("value of a Inner : ",a)
    Inner()
    print("value of a Outer : ",a)

res = Outer("Hello World")
print(res)
print("value of a Global : ",a)
于 2018-03-21T07:28:52.410 に答える