Pythonで関数内からグローバルスコープ変数へアクセスする場合
スコープ関係で悩んだのでメモメモ。
Pythonでは*1、関数内からグローバル変数を参照することができます。
参照
>>> a = 3 # グローバル変数 >>> def test1(): ... print a ... >>> test1() 3
関数内からグローバル変数を参照・表示していることがわかります。
代入
>>> a = 3 # グローバル変数 >>> def test2(): ... a = 10 ... print a ... >>> test2() 10
グローバル変数への代入ができましたできていません。
※追記※
コメントで指摘を頂きましたが、この関数test2での変数aはローカル変数です。以下を見て頂くと分かりやすいかと。
>>> a = 3 # グローバル変数 >>> def test2(): ... a = 10 ... print a ... >>> test2() 10 >>> a 3
このように、関数実行後にグローバル変数aを呼び出すと、何も変化していないことが分かります。
グローバル変数は関数から参照はできますが、代入はできないようです。
参照→代入
>>> a = 3 # グローバル変数 >>> def test3(): ... print a # 参照 ... a = 10 # 代入 ... >>> test3() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in test3 UnboundLocalError: local variable 'a' referenced before assignment
これだとエラーになります。
今回の処理の流れは以下
- グローバル変数aが存在する
- 関数内でaを参照する
- aに値を代入する
このとき、2ではグローバル変数のaが参照されますが、3ではローカル変数の扱いになるみたいです。
エラーも「そんな変数ねーよ!」って内容だし。
つまり、
関数内でグローバル変数の参照・代入は同時にできない
ということになります。
解決方法
global宣言を使います。
>>> a = 3 # グローバル変数 >>> def test4(): ... global a # global宣言 ... print a # 参照 ... a = 10 # 代入 ... >>> test4() 3 >>> a 10
関数の先頭にglobal宣言がついた以外は、先程のものとまったく同じです。
ちゃんと参照と代入が両方ともできていますね。
ただし
スパゲッティコードのもとになりやすいので注意が必要です。
今書いてるコードが既に美味しいパスタ><
*1:他の言語でも大体当てはまると思うけど。