Pythonのglobal変数
短いスクリプトを書いたり、サンプルコードを少し実験してみるときには、私はしっかり作り込んだりせずglobal変数に頼ったりすることが多いです。そういったシーンでは、global変数を参照する際に毎回global
キーワードを記述するのも面倒。省略できるなら省略したい。けどどんなときに省略できるのか詳しくわかっていませんでした。
いくつか実験をしてみましたのでみなさんの参考になればと思います。
まずはわかった結論から
- globalキーワードを省略すると?
-
def
の中など、あるローカル名前空間でglobal
キーワードを省略した場合、書き換えが行われる変数が、グローバル変数と同じ名称だった場合、それはグローバル変数ではなく、新しいローカル変数であると判断されるようです。そして一旦ローカルであると判断されたあとはその名前空間では絶対に同一名称のグローバル変数へのアクセスができなくなるようです。 - 一方で、書き換えを行わないのであれば
global
キーワードを省略してもグローバル変数として扱われるようです。ややこしい。誰だこんなヘンテコルール作ったやつ。
-
- 覚えておくこと
- 開発の流れの中では、まずはグローバル変数を参照する記述をすることが多いのではないかと思います。そのときは
global
キーワードは必要ありません。 - いざ、その変数を書き換えたくなった瞬間!
global
キーワードを書いてください。- 忘れた場合、グローバル変数を参照していたそれまでのコードが、一転してローカル変数への参照となります。
- 1ヶ所書き換えただけなのに、その前から周辺が動かなくなるなんてことも十分あり得ます。
- この法則は覚えておく必要があります。
- 開発の流れの中では、まずはグローバル変数を参照する記述をすることが多いのではないかと思います。そのときは
glb = 30
def func(arg):
lcl = glb * glb # グローバル変数を参照する記述 ok!
return lcl
↓
glb = 30
def func(arg):
if arg == False:
glb = 0 # 新規記述。グローバル変数を書き換えようとした。
lcl = glb * glb # もうグローバル変数を参照していない。
return lcl
実際のコードで確認
#!python3
glb = 30
ret = None
def func0():
return glb # これはglobalを参照している
def func1():
glb = 5 # これはlocal変数
return glb
def func2():
global glb # これはglobalを参照している
glb = 5
return glb
def func3():
lcl = glb # これはglobalを参照している
return lcl
def func4():
glb = glb # エラー。これはlocal変数。不定値参照。
return glb
def func5():
glb = 5 # これはlocal変数
#global glb # エラー。local変数と同一名称のglobal変数
glb = 5
return glb
def reset():
global glb
global ret
glb = 30
ret = None
reset()
print(f"after reset : ret:{ret}, glb:{glb}")
reset()
ret = func0()
print(f"after func0 : ret:{ret}, glb:{glb}")
reset()
ret = func1()
print(f"after func1 : ret:{ret}, glb:{glb}")
reset()
ret = func2()
print(f"after func2 : ret:{ret}, glb:{glb}")
reset()
ret = func3()
print(f"after func3 : ret:{ret}, glb:{glb}")
reset()
ret = func4()
print(f"after func4 : ret:{ret}, glb:{glb}")
reset()
ret = func5()
print(f"after func5 : ret:{ret}, glb:{glb}")
結果
after reset : ret:None, glb:30
after func0 : ret:30, glb:30
after func1 : ret:5, glb:30
after func2 : ret:5, glb:5
after func3 : ret:30, glb:30
Traceback (most recent call last):
File "/Users/shinya.ohtani/Documents/CodeRunner documents/Sample.py", line 52, in <module>
ret = func4()
File "/Users/shinya.ohtani/Documents/CodeRunner documents/Sample.py", line 29, in func4
glb = glb # エラー。これはlocal変数。不定値参照。
UnboundLocalError: local variable 'glb' referenced before assignment