復習を込めて授業をサラッと見ていたらnonlocal
とglobal
に。自問自答してパット答えられなかったのでqiitaに書くことに。
#global and nonlocal
そもそもなんでこんなのが必要なのかというと、(pythonでは)プログラムは一度処理を終えてしまうとメモリが自動的に消えてしまうので次回同じプログラムを開始させても初期状態からスタートしてしまう。状況によってはそれが不都合だとされることがある。そこでnonlocal
(or global
)。これを使えば処理を終えても指定した変数の記録を残して次の処理を実行できるというわけだ。詳しくは一番下の例を。
_
global
says that whenever it seesx0
(that's when thex0
is mentioned inside off2
), we will go for the definition ofx0
in the global frame.
nonlocal
says whenever you seex1
mentioned, we will look forx1
in some frame outside off2
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
を加えると
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
xの中身をそのままキープさせたい時などに役に立ちそう。
def stepper(num):
def step():
nonlocal num
num += 1
return num
return step
>>> stepper(4)()
5
たまたま自分で作ったメモを見つけたのでこれを元に。。
def counter():
count = 0
def counter():
count += 1
return count
return counter
# triggers unboundlocalerror since its not defined inside the counter func.
def counter2():
count = 0
def counter():
count = 0
count += 1
return count
return counter
"""
c = counter2() always returns 1
since each time the counter func gets called,
it creates another local frame with new info unless you have nonlocal within it
"""
def counter3():
count = 0
def counter():
nonlocal count
count += 1
return count
return count
対してglobal
は
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
結果的にglobal
でもnonlocal
でもnested functionの中にある変数(1つのみ)を__globalとして扱うかnonlocal(ある意味local)として扱うか__だけの問題。global
を使えば指定した変数はglobal変数を無視してglobal x
が定義されたところにあるx
を参考にすると。
#ちょっとした問題
>>> x0, y0 = 0, 0
>>> def g1(x1, y1):
... def f2():
... nonlocal x1
... global x0
... x0, x1 = 1,2
... y0, y1 = 1,2
... f2()
... print(x0, x1, y0, y1)
...
>>> g1(0,0)
1, 2, 0, 0
>>print(x0, y0)
1, 0
x0
とx1
がグローバルかノンローカルの違いを表している。
この例はもっとわかりやすいかもしれない。global
はnested funcitonの中に配置しないと意味が無い。
def f():
global x
def g(): x = 3 # Local x
g()
return x
>>> x = 0
>>> f()
0
def f():
def g():
global x
x = 3
g()
return x
>>>x = 0
>>> f()
3
#直感的にわかりやすそうな例
def make_switcher(f,g,x,y):
"""
a function, which takes in two funcs, f and g, and two #s, x and y. It returns a new function that performs f x-times, and then switches to g for y-times, and then back to f, etc. Assume that f and g each take one arg.
>>>crazy_ivan = make_switcher(lambda x: x*x, lambda x: x+1, 2, 1)
>>>crazy_ivan(4)
16
>>>crazy_ivan(5)
25
>>>crazy_ivan(4)
5
>>>crazy_ivan(4)
16
"""
counter = 0
def swithcer(n):
nonlocal counter, f, g, x, y
if counter == x:
counter = 0
f,g = g,f
x, y = y, x
counter += 1
return f(n)
return swithcer
#その他、参考になりそうなもの
pythontutor.comも役に立つが個人的には自分で書いていったほうが楽しいのでレクチャーにあったショートハンドを参考にしながら勉強するのも面白そうだ。分かりやすく、覚えやすい。