こんにちは、ナナです。
Pythonにおいてグローバル変数を利用するときに「global宣言」が必要となるケースがあります。
Pythonを始めたばかりの人は、いったいなぜ「global宣言」なんてものが必要なんだろうと疑問に感じる方もいるでしょう。
実はわたしも最初に見たときは「なんで必要なの?」と思ってました。
本記事では次の疑問点を解消する内容となっています。
それでは、「global宣言」について学んでいきましょう。
「global宣言」が必要なケースと、必要がないケースとは?
global宣言とはグローバル変数に対して、関数の中で値を書き換えるときに必要となる宣言です。
次のように使用されます。
def test_func():
global x # グローバル宣言
x = 200 # グローバル変数のxを書き換え
x = 50 # グローバル変数の定義
test_func()
print("x:", x)
しかし、変数の値を読み取るだけであれば「global宣言」は必要ありません。
def test_func():
print(x) # グローバル変数を読みだして表示
x = 50 # グローバル変数の定義
test_func()
このように、グローバル変数の中身を参照するだけならば、「global宣言」なしでもグローバル変数「x」を値を参照することができます。
ここで、次の疑問が出てきます。
疑問
なぜ、グローバル変数を関数の中で書き換えるときだけ「global宣言」が必要となるのか?読み出すときはいらないのに…
いったい、なぜ「global宣言」が必要となるのか?この記事で解説しましょう。
理由:「global宣言」がないと判断できないことがあるから
理由は簡単。「global宣言」がないと、あることが判断できず困ってしまうからです。
具体的に2つのプログラムを紹介しましょう。
プログラムその①
def test_func():
x = 100
# 関数の中で「x」を表示
print("関数:", x)
# グローバル変数の定義
x = 50
test_func()
# 関数の外で「x」を表示
print("ファイル:", x)
関数: 100
ファイル: 50
プログラムその②
def test_func():
global x
x = 100
# 関数の中で「x」を表示
print("関数:", x)
# グローバル変数の定義
x = 50
test_func()
# 関数の外で「x」を表示
print("ファイル:", x)
関数: 100
ファイル: 100
この2つのプログラムは非常に似ていますが、「global宣言」の有無によって実行された結果が変わります。
この2つのプログラムを判別するために「global宣言」が存在し、必要となる理由なのです。
詳細解説:「global宣言」が必要となる理由
この段階でピンと来る方もいると思いますが、もう少し丁寧に解説しましょう。
Pythonにおける変数定義の特徴 その①
Pythonは変数に対して明確な『変数定義』という構文が存在せず、「変数名への代入処理が現れた時点で、存在しない変数であれば変数定義となる」という特徴があります。
代入が「変数定義を伴う代入の場合」と「代入のみの場合」を明確に示しましょう。
x = 50 # グローバル変数の定義を伴う「代入」
x = 100 # 変数の値を書き換えるただの「代入」
print(x)
1行目の代入時点で「x」は存在していないため、変数「x」は『変数定義を伴う代入』と判断されます。
2行目の代入では、すでに変数「x」は存在しているため、変数定義を伴わない『ただの代入』として判断されます。
変数の『定義』と『代入』の境界線があいまいなことが、「global宣言」が必要な理由につながっています。
Pythonにおける変数定義の特徴 その②
Pythonにおいては『グローバル変数』と同じ名前の変数を、『ローカル変数』として定義することが可能です。
def test_func():
x = 100 # 同名のローカル変数「x」の定義
print(x) # ローカル変数の「x」である「100」が表示
x = 50 # グローバル変数の定義
test_func()
同名の変数名である場合は、関数内の処理ではローカル変数を参照して処理がされます。
このように『グローバル変数』と『ローカル変数』の名前の重複は許されています。
2つの特徴によって引き起こされる問題と解決策
ここまでに説明した特徴①②によって「global宣言」が必要となる理由が判明します。
次のプログラムにおいて、test_func関数の中の「x」は次の2つの可能性があります。
- ローカル変数を定義したとして処理したい
- グローバル変数の値を変更したい
def test_func():
x = 100 # この「x」をグローバルにしたい?ローカルにしたい?
print("関数:", x)
# グローバル変数の定義
x = 50
test_func()
print("ファイル:", x)
この2つのどちらを選択したいかは、皆さん次第でありプログラム側はどちらなのかは判断できません。
つまり、「global宣言」とは、この2つを切り分けるために必要なのです。
グローバル変数の中を書き換えたい場合は、「ここで書き換えている変数xは、グローバル変数ですよ!」と明示するために「global宣言」が必要なのです。
わかりましたか?2つのケースを切り分けるための目印が「global宣言」なんです。
このように切り分けるための印のようなものは、プログラミングの世界ではよくあります。より深く考察することで、その理由がわかります。
なぜ、グローバル変数を読み取るだけのときは「global宣言」は不要なのか?
それでは、続いてグローバル変数を読み取る場合には「global宣言」が不要な理由を解説しておきましょう。
ここまでの内容を理解していれば、結構簡単な理由なんです。
もう一度、読み取りしているプログラムをじっくりと見てみましょう。
def test_func():
print(x)
x = 50 # グローバル変数の定義
test_func()
test_func関数の中には、変数「x」への代入がないため、変数「x」はローカル変数であることがありえません。
これこそが読み取り時においては「global宣言」が不要な理由です。
皆さん、わかりましたか?
言語仕様というものは、必ず何かを実現するために決められたルールであり、意味のないルールなんてないのです。理由を知ることが「本当の意味で使いこなす」ということなんです。