Pythonのglobal宣言文の使い方と構造

182, 2021-02-15

目次

Pythonのglobal文の使い方

プログラミング言語のPythonではグローバル変数と言う変数を扱うことが出来ます。
このグローバル変数を関数などから参照するときに一緒に使われるのがglobal宣言文です。

関数内でグローバル変数に代入を行いたい時はこのglobal文を使います。

この記事ではPythonのglobal文について解説します。
具体的にはglobal文について↓を見ていきます。

  • global文の構造

  • global文の使い方

global文の構造

global文は↓のような構造になっています。

global_stmt ::=  "global" identifier ("," identifier)*

↑の記述はBNFというプログラミング言語の文法を定義するときに使われる記法です。
global_stmtというのがglobal文のことです。そして::=の右側にあるのがglobal文の構造です。
↑のBNFを見るとglobal文はglobalというキーワードではじまり、複数の識別子(identifier)を取ります。

↑のBNFからわかるglobal文の記述例は↓のようになります。

global var1
global var1, var2

↓のように変数名を指定しないglobal文は未定義で、不正な文法になります。

global

また、↓のようにカンマが余る書き方も不正な文法になります。

global var1, var2,

global文で参照する変数名は、同じブロックでglobal文より前方で使うことが出来ません。
これはたとえば↓のようなコードです。

var1 = 0
global var1

↑のコードを実行すると↓のようなエラーになります。

SyntaxError: name 'var1' is assigned to before global declaration

それからglobal文で参照する変数名はforループのループ制御ターゲットや、class定義、関数定義、import文、変数アノテーションで仮引数として使えません。
これはたとえば↓のようなコードがNGということです。

var1 = 0

def f(var1):
    global var1

f(1)

↑のコードを実行すると↓のようなエラーになります。

SyntaxError: name 'var1' is parameter and global

global文の使い方

global文はglobal文で参照する変数名をグローバル変数としてPythonに認識させる文です。
つまり「Pythonさん、これはグローバル変数ですよ」とPythonに教えてあげるのがglobal文です。

関数などからグローバル変数を参照し、そのグローバル変数に代入を行いたいとします。
ふつうに代入を行うと、その代入は関数のローカル変数の初期化になってしまいます。

g = 0  # <- グローバル変数

def f():
    g = 1  # <- このgは関数fのローカル変数扱いになる

f()  # <- グローバル変数に変更が加えられるか?
print(g)  # <- 結果は0. グローバル変数には変化なし

つまりPythonでは普通にやってると関数内からグローバル変数に値を代入することが出来ません。
それでは不便なので生まれたのがglobal文です。
変数への代入の前にglobal文で変数名をグローバル変数だとPythonに認識させれば、グローバル変数への代入が可能になります。

g = 0  # <- グローバル変数

def f():
    global g  # <- gはグローバル変数だとPythonに教えてあげる
    g = 1  # <- このgへの代入はグローバル変数gに対して行われる

f()  # <- グローバル変数に変更が加えられるか?
print(g)  # <- 結果は1. 関数fでグローバル変数に代入が行われた

↑のコードではグローバル変数gを作っています。
そして関数fでそのgに代入を行っています。
代入の前にglobal gとすることでPythonにgはグローバル変数だと教えてあげます。
そして代入(g = 1)を行います。この代入はグローバル変数gに対して行われます。

関数fが終了し、gの中身を見るとgの中身が書き換えられているのがわかります。
このようにglobal文を使うとグローバル変数に対して代入を行うことが出来ます。

global文のエラー集

便利なglobal文ですが、文脈によってはエラーになります。
ここではそのエラー例をいくつか上げてみたいと思います。

for文のカウント変数に対してglobal文を使う

for文のカウント変数に対してglobal文を使うことは出来ません。

def f():
    for i in range(4):
        global i

f()

↑のコードは↓のようなエラーになります。

SyntaxError: name 'i' is assigned to before global declaration

仮引数に対してglobal文を使う

関数の仮引数などに対してglobal文を使うことは出来ません。
ちなみに仮引数とは実引数と対になる言葉で、関数の定義側の引数のことを言います。

def f(arg):
    global arg

f(1)

↑のコードを実行すると↓のような結果になります。

SyntaxError: name 'arg' is parameter and global

また同じような理由でクラスのメソッドの引数にも使えません。

おわりに

今回はglobal文について見て見ました。
グローバル変数は大きなプロジェクトではあまり使う機会がありませんが、小さなプロジェクトでは簡便さのためによく使われることがあります。
グローバル変数に代入をしたい場合はこのglobal文を思い出してみてください。

グローバル変数で遊ぼう

Cの時代を感じろ!