この問題は次の「クロージャ」の例から出ていますが、まず結果を推測してみましょう。
def funX():
x = 5
def funY():
nonlocal x
x += 1
return x
a = funX()
print(a())
print(a())
print(a())
消す:
6
7
8
なぜこのローカル変数 x がグローバル変数と同じなのか疑問に思われるかもしれません。x は呼び出されるたびに 5 に再初期化されるべきではないでしょうか?
実際、注意深く見てみると、 a = funX() の場合、 a 変数が再割り当てされない限り funX() は解放されないことがわかります。これは、ローカル変数 x が再初期化されないことを意味します。
理解を容易にするために、外部関数に別のコード print(x) を追加します。
def funX():
x = 5
print(x)
def funY():
nonlocal x
x += 1
return x
return funY
a = funX()
print(a())
print(a())
print(a())
もう一度実行してみると、ローカル変数 x がグローバル変数「になる」理由が表示されます。
5
6
7
8
それでも理解できない場合は、コードを再度変更すると、次のことがわかります。
funX() を変数 a に代入する過程で "5" が生成されます。
文を短くしましょう:
funX() を変数 a に代入する過程で "5" が生成されます。割り当てプロセス中に生成される
つまり、システムが a = funX() を実行すると、funX() 関数が呼び出され、print(x) 命令が実行され、値 funY が返されます。このとき、a の値は funY であり、内部関数 funY() は条件を暗黙的に示しますx=5
funY() を独立した関数とみなした場合、a() を 3 回呼び出すプロセスは、次の命令を実行することと同じになります。
>>>x = 5
>>>def funY():
global x
x += 1
return x
return funY
>>>funY()
6
>>>funY()
7
>>>funY()
8
したがって、問題の核心は、a = funX() は代入処理であり、a 変数が再代入されない限り funX() は解放されず、ローカル変数 x は 5 に初期化されません。