Python nonlocal
ステートメントは何をしますか(Python 3.0以降)。
公式のPythonウェブサイトにはドキュメントがなく、help("nonlocal")
も機能しません。
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()
のx
はouter()
の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
要するに、外部(ただし、非グローバル)スコープ内の変数に値を割り当てることができます。すべての厄介な詳細については、 PEP 3104 を参照してください。
「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ですが、最初のバージョンは初心者にとってもう少し明白になるようです。返された関数を呼び出すことにより、ジェネレーターを適切に使用することは、混乱の共通点です。最初のバージョンは明示的に関数を返します。
help( 'nonlocal')
nonlocal
ステートメントnonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
nonlocal
ステートメントにより、リストされた識別子は、最も近い囲みスコープ内の以前にバインドされた変数を参照します。バインディングのデフォルトの動作は、最初にローカル名前空間を検索することであるため、これは重要です。このステートメントにより、カプセル化されたコードは、グローバル(モジュール)スコープ以外のローカルスコープ外の変数を再バインドできます。
nonlocal
ステートメントにリストされている名前とは異なり、global
ステートメントにリストされている名前は、囲みスコープ内の既存のバインディングを参照する必要があります(新しいバインディングを作成するスコープは明確に決定できません)。
nonlocal
ステートメントにリストされている名前は、ローカルスコープ内の既存のバインディングと競合してはなりません。こちらもご覧ください:
PEP 3104-外部スコープの名前へのアクセス
nonlocal
ステートメントの仕様。関連するヘルプトピック:グローバル、NAMESPACES
ソース: Python言語リファレンス
@ooboo:
ソースコード内の参照ポイントに「最も近い」ものを取ります。これは「語彙スコーピング」と呼ばれ、40年以上の標準となっています。
Pythonのクラスメンバーは、実際には__dict__
と呼ばれる辞書にあり、レキシカルスコープによって到達することはありません。
nonlocal
を指定せずにx = 7
を指定すると、新しいローカル変数「x」が作成されます。 nonlocal
を指定すると、「最も近い」「x」を見つけて割り当てます。 nonlocal
を指定し、「x」がない場合、エラーメッセージが表示されます。
キーワードglobal
は、一番外側のものを除いて他のすべての "x"を喜んで無視するので、いつも奇妙に思えました。奇妙な。
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)
「非ローカル」ステートメントの個人的な理解(およびPythonおよびプログラミング全般に不慣れなため、失礼します)は、「非ローカル」は反復関数内ではなくグローバル機能を使用する方法であるということです。コード本体。必要に応じて、関数間のグローバルステートメント。
Python 3リファレンス からの引用:
非ローカルステートメントにより、リストされた識別子は、グローバルを除く最も近い囲みスコープで以前にバインドされた変数を参照します。
リファレンスで述べたように、いくつかのネストされた関数の場合、最も近い囲んでいる関数の変数のみが変更されます:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
x = 2
innermost()
if x == 3: print('Inner x has been modified')
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Inner x has been modified
「最近接」変数は、数レベル離れている場合があります。
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Outer x has been modified
ただし、グローバル変数にすることはできません。
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
inner()
x = 0
outer()
if x == 3: print('Global x has been modified')
# SyntaxError: no binding for nonlocal 'x' found
「非ローカル」内部関数(つまり、ネストされた内部関数)を使用すると、読み取りと「write」権限外側の親関数の特定の変数の場合。また、非ローカルは内部関数内でのみ使用できます。例:
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)