Pythonnonlocal
ステートメントは何をしますか(Python 3.0以降)?
Pythonの公式Webサイトにはドキュメントがなく、help("nonlocal")
機能しません。
Pythonnonlocal
ステートメントは何をしますか(Python 3.0以降)?
Pythonの公式Webサイトにはドキュメントがなく、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 ですが、最初のバージョンは初心者にとってはもう少し明白であるように思われます。返された関数を呼び出してジェネレーターを適切に使用することは、よくある混乱のポイントです。最初のバージョンは明示的に関数を返します。
@ooboo:
これは、ソースコードの参照ポイントに「最も近い」ものを取ります。これは「レキシカルスコープ」と呼ばれ、40年以上前から標準となっています。
Pythonのクラスメンバーは、実際にはと呼ばれる辞書__dict__
にあり、字句スコープで到達することはありません。
指定せずに実行するnonlocal
とx = 7
、新しいローカル変数「x」が作成されます。を指定するnonlocal
と、「最も近い」「x」が検索され、それに割り当てられます。指定nonlocal
して「x」がない場合は、エラーメッセージが表示されます。
キーワードglobal
は、最も外側の「x」を除いて他のすべての「x」を喜んで無視するので、私にはいつも奇妙に見えました。変。
help('nonlocal')
nonlocal
ステートメント
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
この
nonlocal
ステートメントにより、リストされたIDは、最も近い囲みスコープ内の以前にバインドされた変数を参照します。バインディングのデフォルトの動作は最初にローカル名前空間を検索することであるため、これは重要です。このステートメントを使用すると、カプセル化されたコードで、グローバル(モジュール)スコープ以外のローカルスコープ外の変数を再バインドできます。ステートメントにリストされている名前は、
nonlocal
ステートメントにリストされている名前とは異なりglobal
、囲んでいるスコープ内の既存のバインディングを参照する必要があります(新しいバインディングを作成するスコープを明確に決定することはできません)。ステートメントにリストされている名前
nonlocal
は、ローカルスコープ内の既存のバインディングと衝突してはなりません。参照:
PEP3104-外部スコープの名前へのアクセスステートメント
の仕様。nonlocal
関連するヘルプトピック:グローバル、NAMESPACES
「非ローカル」ステートメントに関する私の個人的な理解 (そして、私は Python とプログラミング全般に慣れていないので失礼します) は、「非ローカル」は、コード自体ではなく、反復関数内でグローバル機能を使用する方法であるということです。 . 必要に応じて、関数間の Global ステートメント。
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)
「非ローカル」内部関数 (つまり、ネストされた内部関数) を使用すると、外部親関数の特定の変数に対する読み取りと「書き込み」許可を取得できます。また、非ローカルは内部関数内でのみ使用できます。例:
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)