(1時間4,000円の伴走型ビデオチャット指導も受付中!)
Pythonの「グローバル変数」をマスターする:スコープの仕組みと適切な使い分け
![]()
【Yuki】
Hirokiくん、こんにちは。今日はPythonを勉強していく中で、多くの人が少し戸惑ってしまう「変数の範囲」、つまりスコープとグローバル変数についてお話ししようと思います。……あ、あまり難しい顔をしないでくださいね。ゆっくり、順番に説明していきますから。
![]()
【Hiroki】
Yukiさん、こんにちは!よろしくお願いします。スコープ……ですか。以前、関数の中で作った変数が、関数の外で使えなくて困ったことがあったんです。それに関係することでしょうか?
![]()
【Yuki】
ええ、まさにそれです。素晴らしい気づきですね……。Pythonでは、変数が「どこで定義されたか」によって、その変数が「どこから見えるか」が決まっているんです。これをスコープ(範囲)と呼びます。まずは、一番大きな範囲である「グローバル変数」から見ていきましょう。
グローバル変数とローカル変数の違い
![]()
【Yuki】
まず、プログラムの「一番外側」で定義された変数のことをグローバル変数と呼びます。これは、プログラムの中ならどこからでも参照できる変数です。逆に、関数の「内側」で定義された変数はローカル変数と呼ばれて、その関数の中でしか使えません。
![]()
【Hiroki】
なるほど。外側にあるのがグローバル、内側にあるのがローカル、ということですね。実際にコードで見るとどうなるんでしょうか?
![]()
【Yuki】
そうですね、簡単な例を書いてみます。
# これはグローバル変数です
message = "こんにちは、グローバル変数です"
def say_hello():
# これはローカル変数です
local_msg = "私はローカル変数です"
print(message) # グローバル変数を参照できます
print(local_msg) # ローカル変数を参照できます
say_hello()
print(message) # 関数の外でもグローバル変数は使えます
# print(local_msg) # ここで実行するとエラーになります(NameError)
![]()
【Hiroki】
本当だ。関数の中から外の message は見えるけど、関数の外から中の local_msg を見ようとするとエラーになっちゃうんですね。
![]()
【Yuki】
はい。ローカル変数は、その関数が実行されている間だけ、メモリの中に一時的に作られる「使い捨て」の箱のようなものなんです。関数が終わると、その箱は片付けられてしまいます……。少し寂しい気もしますけれど、そうすることで、他の場所で同じ名前の変数を使っても混ざらないようになっているんですよ。
グローバル変数を書き換える「global」キーワード
![]()
【Hiroki】
あの、Yukiさん。もし、関数の中からグローバル変数の値を書き換えたいときは、どうすればいいんですか? 普通に代入すればいいんでしょうか?
![]()
【Yuki】
そこがPythonの少し注意が必要なところです……。実は、関数の中でグローバル変数と同じ名前の変数に値を代入しようとすると、Pythonは新しい「ローカル変数」を作ったと判断してしまうんです。
![]()
【Hiroki】
えっ、書き換えたつもりでも、別物になっちゃうんですか?
![]()
【Yuki】
そうなんです。ちょっとこのコードを見ていただけますか。
count = 0
def update_count():
count = 10 # これだと新しい「ローカル変数」が作られてしまいます
print(f"関数内での値: {count}")
update_count()
print(f"関数外での値: {count}")
![]()
【Hiroki】
あ、本当だ。関数の中では10になっているのに、外に戻ると元の0のままですね。これじゃ、グローバル変数を変更したことになりません。
![]()
【Yuki】
そうなんです。そこで、明示的に「この count は外側のグローバル変数ですよ」と教えてあげる必要があります。そのために使うのが、globalキーワードです。
count = 0
def update_count():
global count # これから使うcountはグローバル変数だと宣言します
count = 10
print(f"関数内での値: {count}")
update_count()
print(f"関数外での値: {count}")
![]()
【Hiroki】
なるほど! global count と一行入れるだけで、ちゃんと外側の変数にアクセスできるようになるんですね。これですっきりしました。
スコープの優先順位「LEGBルール」
![]()
【Yuki】
もう少しだけ深いお話をしても大丈夫でしょうか……? Pythonが変数を探すときには、実は決まった順番があるんです。それをLEGBルールと呼びます。
![]()
【Hiroki】
エル・イー・ジー・ビー……? 何かの略称ですか?
![]()
【Yuki】
はい、以下の4つの頭文字をとったものです。
- L (Local): 今いる関数の中(ローカルスコープ)
- E (Enclosing): 関数を包んでいる、さらに外側の関数の中(エンクロージングスコープ)
- G (Global): ファイルのトップレベル(グローバルスコープ)
- B (Built-in): Pythonが最初から持っている名前(組み込みスコープ。例えば
printやlenなど)
![]()
【Hiroki】
まずは一番近いところから探して、なければどんどん外側に探しに行く、というイメージですね。
![]()
【Yuki】
その通りです。だから、もしグローバル変数と同じ名前のローカル変数が定義されていると、Pythonは一番近い「ローカル変数」を優先して使ってしまいます。これを「変数の隠蔽(シャドウイング)」と呼んだりもします……。名前が重なるとややこしくなるので、できるだけ避けたいことですね。
実践:最新のAI APIを利用した例
![]()
【Hiroki】
グローバル変数って、どんな時に使うのが一番良いんでしょうか? あまり使いすぎない方がいい、とも聞いたことがあるのですが……。
![]()
【Yuki】
おっしゃる通り、グローバル変数を多用すると、どこで値が変わったか分からなくなってしまうので、必要最小限にするのが良いとされています。……ただ、例えば「プログラム全体で使う設定値」などを保持しておくのには便利ですよ。最近のAI開発、例えばGoogleのGemini APIを使う際の設定などで考えてみましょうか。
![]()
【Hiroki】
あ、ぜひ見てみたいです!
![]()
【Yuki】
今は google-genai という新しいライブラリを使うのが主流になっています。例えば、APIキーやモデル名をグローバルな設定として置いておくような書き方ですね。
from google import genai
# グローバルな設定として定数(のように扱う変数)を定義
# Pythonでは慣習として、変更しないグローバル変数は全て大文字で書きます
API_KEY = "YOUR_API_KEY"
MODEL_ID = "gemini-2.0-flash-exp" # 最新のGemini 2.0モデルを指定
def generate_text(prompt):
# クライアントの作成
client = genai.Client(api_key=API_KEY)
# グローバル変数MODEL_IDを参照して生成
response = client.models.generate_content(
model=MODEL_ID,
contents=prompt
)
return response.text
# 実行
result = generate_text("Pythonのグローバル変数について、短く励ましのメッセージを書いてください")
print(result)
![]()
【Hiroki】
なるほど! APIキーやモデル名はプログラムのいろんな場所で使うから、こうしてグローバルな場所に置いておけば、モデルを gemini-1.5-flash から gemini-2.0-flash-exp に変えたい時も一箇所書き換えるだけで済みますね。
![]()
【Yuki】
はい。このように、複数の関数から参照される「変更されない値(定数)」として使うのは、とても良いグローバル変数の使い方だと思います。ただ、先ほどの global キーワードを使って、あちこちの関数から値をコロコロ書き換えるのは、バグの原因になりやすいので注意してくださいね……。
![]()
【Hiroki】
わかりました。基本は参照するだけにして、書き換えるのはどうしても必要な時だけにするようにします。
グローバル変数のリスクと回避策
![]()
【Yuki】
Hirokiくん、理解が早くて助かります……。なぜ書き換えを避けるべきか、もう少し補足させてください。例えば、大きなプログラムで何十個も関数があったとします。その中のどこかで誰かがこっそり global 変数を書き換えてしまったら、他の関数が動かなくなった時に原因を探すのがとても大変になってしまうんです。
![]()
【Hiroki】
たしかに、自分の知らないところで勝手に箱の中身が入れ替わってたら、びっくりしちゃいますね。
![]()
【Yuki】
そうですよね。ですので、基本的には「関数に引数として値を渡し、結果を戻り値として受け取る」という形にするのが一番安全です。どうしても状態を保持したい場合は、クラス(オブジェクト指向)を使うのが一般的ですが……それはまた別の機会にお話ししましょう。
![]()
【Hiroki】
少しずつステップアップしていけばいいんですね。安心しました。
名前空間(Namespace)の意識
![]()
【Yuki】
最後に、名前空間についても少しだけ。Pythonは、変数名を辞書のような形式で管理しています。
globals() という関数を使うと、今どんなグローバル変数が定義されているかを実際に見ることができるんですよ。
![]()
【Hiroki】
えっ、中身が見られるんですか?
![]()
【Yuki】
はい。ちょっと試してみましょう。
x = 100
y = "Hello"
# グローバルな名前空間を表示
print(globals())
![]()
【Hiroki】
うわっ、なんだかたくさん出てきました! x や y 以外にも、最初から設定されているいろんな値があるんですね。
![]()
【Yuki】
そうなんです。Pythonが裏側で準備してくれているものがたくさんあることがわかりますよね。私たちが書くコードは、この広大な名前空間の一部を使わせてもらっているような感覚なんです……。そう思うと、名前がぶつからないように大切に変数を扱いたくなりませんか?
![]()
【Hiroki】
確かにそうですね。自分の作った変数がこのリストに並んでいるのを見ると、プログラムの一部になったんだなって実感します。
![]()
【Yuki】
……ふふ、そう言ってもらえると嬉しいです。誰かの役に立つために書かれた、たった一行の小さなツールでも、そこには必ずスコープがあって、変数が一生懸命に値を運んでいるんですよね。そう考えると、プログラムが少しだけ愛おしく思えてきませんか?
![]()
【Hiroki】
はい! 今日はスコープとグローバル変数について、すごくよく分かりました。Yukiさん、丁寧に教えてくれてありがとうございました。
![]()
【Yuki】
いえ……こちらこそ、熱心に聞いてくれてありがとうございます。もしまた、変数たちが迷子になったり、値がうまく届かなかったりしたら、いつでも聞いてくださいね。夜はまだ長いですから……、自分のペースでゆっくり学んでいきましょう。
![]()
【Hiroki】
ありがとうございます。またよろしくお願いします!
参考資料
- Python 公式ドキュメント: 実行モデル (名前と束縛)
- Python 公式ドキュメント: global 文
- Google GenAI SDK (GitHub)
- Gemini API documentation
この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。
「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。
- 専門家の知見に基づいた、保守性の高いコード設計
- AIの専門家による、Gemini API等の最新AIを組み合わせた高度な自動化
- ChatGPT等が生成したコードのデバッグ・最適化
「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。
初心者から始められるPythonレッスン
● 月額4,000円で質問し放題!!
● 完全オンライン
● 翌日までには必ず返信
● 挫折しない独自の学習メソッド
● 圧倒的高評価!!
● テキストベースで時間を選ばない
● 4,000円/60分の伴走型ビデオチャット指導も可能
● 高品質なサンプルコード
詳細はこちら

