Pythonのグローバル変数の使い方【global】
- 作成日: 2023-12-26
- 更新日: 2023-12-26
- カテゴリ: Python
Pythonのグローバル変数はどう使う?
グローバル変数とはコードにおいてグローバルな領域に宣言される変数のことを言います。
このような変数はグローバル変数と呼ばれ、いっぽうグローバルでないローカルな変数はローカル変数と呼ばれます。
コードにしてみるとこれの違いは明確です。
# グローバル変数
global_var = 'Hello'
def main():
# ローカル変数
local_var = 'World'
この記事ではPythonでグローバル変数を扱う方法を解説します。
Pythonにおけるグローバル変数とは何か?
Pythonにおけるグローバル変数とはなんでしょうか?
たとえばmain.py
というファイルを作ったとします。
そしてこのファイルに以下のような変数を定義しました。
# グローバル変数
one = 1
two = 2
three = 3
このような変数はすべてグローバル変数と呼ばれます。
つまり上記のone
, two
, three
はすべてグローバル変数です。
Pythonにおけるローカル変数とは何か?
ではローカル変数とは何になるのか?
変数を定義しただけでグローバル変数になるのであれば、ローカル変数などないのではないか?
ということなんですが、これはたとえば関数内の変数がローカル変数に当たります。
def main():
four = 4
five = 5
six = 6
上記のfour
, five
, six
はすべてローカル変数であり、グローバル変数ではありません。
グローバル変数はファイルの一番外側にべた書きされている変数で、ローカル変数は関数の中の変数。
という風に覚えておけばいいと思います。
Pythonでグローバル変数を参照する
Pythonでグローバル変数を使いたい場合は以下のようにグローバル変数を参照します。
one = 1
print(one) # 1
また関数内からグローバル変数を参照したい時もあります。
one = 1
def main():
print(one) # 1
上記のようにすればグローバル変数は参照できます。
グローバル変数が参照できない?
少し込み入ったコードではグローバル変数が参照できない時があります。
たとえば以下のようなコードです。
d = {'one': 1}
def main():
d = {}
def sub():
print(d['one'])
# KeyError: 'one'
sub()
main()
グローバル変数としてd = {'one': 1}
を定義しています。
そしてmain関数内ではd = {}
でローカル変数を。
そしてsub関数内ではprint(d['one'])
でd
を参照しています。
しかしこのコードを実行すると、print(d['one'])
でエラーになります。
sub関数内でd
を参照してこれはグローバルのd
だと期待しますが、実際にはmain関数内のd
が参照されてしまっています。
この場合は後述するglobal文を使うことで解決できます。
以下はglobal文で解決しているコードです。
d = {'one': 1}
def main():
d = {}
def sub():
global d
print(d['one']) # 1
sub()
main()
Pythonでグローバル変数を変更する
グローバル変数を変更する場合は注意が必要です。
グローバルスコープ、つまりグローバルな領域でグローバル変数を変更する場合は以下のように変更できます。
one = 1
print(one) # 1
one = 2
print(one) # 2
しかし関数内からグローバル変数を変更しようとした場合ですが、以下の動作を見てください。
one = 1
def main():
one = 2
print(one) # 2
main()
print(one) # 1
上記のコードで注目してほしいのが、main関数を呼び出した後の変数one
の値です。
main関数の中でone
を2
に変更しています。これは成功しているように見えます。
しかしmain関数を呼び出し終わって、one
を出力すると1
のままです。
main関数内でone
を変更しているのに、なぜmain関数が終わったら変更されないままになっているのでしょうか?
実はこれはPythonの言語仕様によるもので、Pythonではone = 2
というのがグローバル変数への代入なのか、それともローカル変数として新しく定義しているのか、というのが判断が付かないのです。
ですのでこの場合は、Pythonはローカル変数の定義として処理します。
つまり
def main():
one = 2
print(one) # 2
上記のone = 2
のone
はmain関数内のローカル変数になっているわけですね。
これを確認するにはid()
でオブジェクトのアイデンティティーを確認します。
オブジェクトのアイデンティティーとはオブジェクトに割り振られる一意に決まるナンバーのことです。
one = 1
print(id(one))
# 140710367270672
def main():
one = 2
print(id(one))
# 140710367270704
main()
print(id(one))
# 140710367270672
上記のコードを見ますと、main関数内のone
だけアイデンティティーが異なっているのがわかります。
これはmain関数内のone
がグローバル変数のone
とは違うオブジェクトであることを表しています。
プログラマーはone
をグローバル変数だと思って変更するわけですが、実際にはローカル変数になっているということです。
global文
この問題を解決するにはglobal文を使います。
global文 — Python 3.12.1 ドキュメント
このglobal文で変数を宣言するとPythonはその宣言された変数をグローバル変数として扱います。
ですのでmain関数内のone
をglobal文で宣言すればそれはグローバル変数として処理されます。
one = 1
def main():
global one
one = 2
print(one) # 2
main()
print(one) # 2
上記のコードではmain関数内でone
をグローバル宣言しています。
よってmain関数内のone
はグローバル変数だとPythonは解釈します。
そのあとにone = 2
で変数の値を変更しています。
main関数の呼び出し後にone
を参照すると、ちゃんと値が変更されているのがわかります。
global文の文法
global文の文法は以下のようになっています。
global_stmt ::= "global" identifier ("," identifier)*
この文法の記法はBNF(バッカス・ナウア記法)と呼ばれるものです。
プログラミング言語の開発などで使われる言語の設計を記述する記法です。
上記のBNFを見ますと、global_stmt
(グローバル文)は
"global" identifier ("," identifier)*
という中身になっています。
まず最初にglobal
というキーワードが入り、そのあとにidentifier
(識別子)が書かれます。
識別子は変数などのことです。
そしてカンマ(,
)で区切られてさらにidentifier
が0個以上書けるようになっています。
この文法を参考にすると以下のコードが合法になります。
global one
global one, two
global one, two, three
global文はPythonのパーサーに対する指示句(directive)になっています。
この指示句はglobal文と同時に読み込まれたコードに対してのみ有効です。
別ファイルのグローバル変数を参照する
別ファイルのグローバル変数を参照するにはどうしたらいいでしょうか?
たとえば以下のようなsub.py
というファイルがあります。
hello = 'Hello'
このsub.py
のグローバル変数であるhello
をmain.py
内で参照するにはどうしたらいいのか?
この場合は以下のように参照します。
import sub
print(sub.hello) # Hello
from sub import hello
print(hello) # Hello
import sub
のようにsub.py
をインポートして、ドット演算子でsub.hello
のように参照できます。
またfrom sub import hello
のようにすれば、hello
を参照することができます。
グローバル変数の命名規則
グローバル変数の命名規則ですが、これはプロジェクトによってコーディングルールが変わりますので、一概にこうしろとは言えません。
慣例的には変数の接頭辞(プリフィックス)にg_
を付けることが多いようです。
g
はglobal
のg
です。
g_hello = 'Hello'
gWorld = 'World'
なぜこのようなプリフィックスを必要とするのかと言うと、グローバル変数はどこからでも参照できるため、スコープが区切られていません。
区切られているとしたらモジュール単位です。
ですので、どこからでも参照できてしまう変数がよく使われる名前になっていると、紛らわしいことがあります。
よってg_
などのプリフィックスを付けることがあります。
グローバル変数の初期化
グローバル変数の初期化は関数としてできるようにしておくと、初期化処理などが走ったときにその関数を呼び出すだけで済みます。
たとえばinit_globals()
という関数を作ってグローバル変数を初期化します。
one = 1
two = 2
def init_globals():
global one, two
one = 1
two = 2
one = 10
two = 20
init_globals()
print(one, two) # 1 2
グローバル変数は避けるべきか?
一般的にはグローバル変数は開発では避けた方がいいと言われることが多いです。
グローバル変数はスコープが広大なため、いろいろなコードに影響を与える恐れがあるからです。
グローバル変数は使わない、という開発者の人も多いかと思います。
Pythonにはクラスがありますので、クラスのインスタンス変数として変数を定義すれば、そのインスタンス変数をクラス内のグローバル変数のように使えます。
よってクラスを作るのがPython的には便利かもしれません。
しかしクラスが無い言語では、たとえばC言語などではグローバル変数は多用されることがあります。
これはファイルをクラスと見立てて、グローバル変数をインスタンス変数かのように使い、関数をメソッドのように使うという感じです。
実際はファイルはクラスではなくインスタンスも生成されないため、クラスとは違うのですがC言語などは古の時代からこのような設計がよく行われていました。
そのためグローバル変数も使いようによっては便利、と言えるかもしれないので一概にグローバル変数は悪だ、ということは難しいと思います。
関連記事
Djangoでオブジェクトを一括作成・更新【bulk_create, bulk_update】
DjangoのModel.objects.filter()の使い方【QuerySet】
Djangoのmodelのcreate()の使い方【Python】
Django入門: ルートの設定 ~ 簡単な一行掲示板アプリを作る その4【Windows10】
NumPyのappend()の使い方: 配列の末尾に要素を追加
Numpyのarangeの使い方: 指定範囲の数列を生成する
Python3でYoutube Data APIを使ってキーワード検索する
PythonからC言語(my.puts)を呼び出して実行する