Pythonのglobalによるグローバル変数の参照と使い方をわかりやすく解説

スポンサーリンク
スポンサーリンク
amazon
スマイルSALE
--:--:--
~
ad. 価格範囲を指定して商品を探せます

globalの概要

関数内からグローバル変数を使うPython予約語

global

概要 global(グローバル)は、関数(ローカルスコープ)の内部から、その外側(グローバルスコープ)で定義された変数を「直接上書き・修正する」ことをPythonシステムに明示するためのキーワードです。Pythonの言語仕様では、関数内で変数に値を代入すると自動的に「その関数専用のローカル変数」が作られてしまいますが、global を宣言することで関数の壁を突破し、外側のデータにアクセスを同期させることができます。

わかりやすく説明 global は、関数の中から外の世界にある変数に向けて「新しく同姓同名の変数を作り直すんじゃなくて、外のエリアにあるあの変数をそのまま連動させて使うよ!」と指差しでロックオンする命令です。これを使わないと、関数の中と外で名前が同じだけの「全くの別物の変数」として扱われ、外側のデータを変更することができなくなります。

  • global 変数名 と宣言することで、関数の最外層(モジュール直下)で用意された変数への直接的な上書き権限を取得します。
  • この宣言を入れずに関数内で値を代入した場合、その変数は関数が終了すると同時にメモリから消滅する「刹那的なローカル変数」として孤立します。
  • プログラムのどこからでもデータが書き換わってしまうバグ(副作用)を誘発するため、実務の設計においては極力使用を避けるべきとされている諸刃の剣の予約語です。

globalの考え方をイメージで理解

globalの基本的な使い方

関数の外側でゼロ管理されている counter という大元の変数に対し、関数の中からアクセスして数値をプラス1加算する最も標準的な記述です。

# global を使ったグローバル変数の変更
counter = 0  # 関数の外にある変数(グローバル変数)

def increment():
    global counter  # 外の世界の「counter」を直接イジることを宣言
    counter += 1    # 大元の変数が直接プラス1される

increment()
print(counter)  # 結果: 1 (外側の変数も連動して書き換わっています)
  • global counter の防網によって、インデントの内部と外部の変数が完全に同一のメモリ空間として同期されます。

globalがない場合の挙動(初心者がハマる罠)

もし global 宣言の記述を忘れてしまうと、Pythonは「関数の中に同姓同名の別人が新しく引っ越してきた」と自動解釈してしまいます。

# global の宣言を忘れた場合
counter = 0  # 外の変数(グローバル変数)

def increment_fail():
    counter = 1  # 💡外とは無関係の「新しいローカル変数」が関数内で勝手に作られる
    print(f"関数内の counter: {counter}")  # 結果: 1

increment_fail()
print(f"グローバルの counter: {counter}")  # 結果: 0 (外側は大元の設定のまま微動だにしていません!)

globalを使った複数変数の同時操作

変更したいグローバル変数が複数ある場合、ひとマスの global の後ろにカンマ , で並べることによって、一括で操作対象に指定できます。

# 複数のグローバル変数を同時に指定
x = 10
y = 20

def update_globals():
    global x, y  # xとyの両方を外の宇宙から引っ張ってくる
    x += 5
    y *= 2

update_globals()
print(x, y)  # 結果: 15 40

【重要】値の「読み取り(参照)」だけならglobalは不要

Pythonの文法規則として、外側の変数の値を「変更(再代入)」するときだけ global の明示が必要になります。ただ単に中身を覗き見てプリントしたり、条件分岐に使うだけ(読み取り専用)であれば、global の記述は一切不要です。

# 読み取りだけのケース
system_status = "稼働中"

def check_status():
    # データを書き換えないのであれば、宣言なしで外のグローバル変数をそのまま参照可能
    print(f"現在のシステムステータスは {system_status} です") 

check_status()  # 結果: 現在のシステムステータスは 稼働中 です

globalの注意点

  • UnboundLocalErrorを引き起こす順序の罠(最重要バグ):関数内で global 宣言を記述していない状態のまま、同じ変数に対して「参照」と「代入」を混在させると、Pythonのコンパイラが変数の所属を見失い、UnboundLocalError という深刻なエラーを吐き出して処理が即座にクラッシュします。
    # 【クラッシュする致命的な失敗コード】
    score = 100
    
    def adjust_score():
        # 宣言がないのに、ここで外の score を見ようとする
        print(score) 
        # しかし同じ関数内で代入も行っているため、Pythonが「ローカル変数なのか?」と大混乱を起こす
        score = score + 10 
    
    adjust_score()
    # エラー内容: UnboundLocalError: local variable 'score' referenced before assignment
    
    # 【globalを明示して位置関係を整理した正しい対策コード】
    def adjust_score_safe():
        global score # 最初に所属をグローバルであると断定する
        print(score)
        score = score + 10 # 安全に上書きが成功します
    
    adjust_score_safe()
  • 関数の独立性(カプセル化)が破壊されテスト不能になる:優れたプログラムにおける関数とは、引数(インプット)を受け取って戻り値(アウトプット)を返す「単体で動作する綺麗なレゴブロック」であるべきです。global を多用したコードは、外側の変数の状態に依存(密結合)してしまうため、その関数単体をテストすることが困難になり、システム拡張時の最大の足かせになります。

globalのよくある質問

Q: 実務において `global` を使わずに、関数の外にある変数を安全にアップデートする「プロ推奨の綺麗な書き方」を教えてください。
A: global で外側を汚染するのではなく、関数側は return(戻り値)で加工済みの値をお土産として外に放り出し、外側のメインストリームで変数に上書き代入する設計が実務における100点満点の綺麗なアプローチです。

# 【アンチパターン:変化の追跡がしにくい悪いコード】
user_points = 50
def add_points_bad():
    global user_points
    user_points += 10

add_points_bad()

# 【プロ推奨:引数と戻り値で完結させる洗練された対策コード】
user_points = 50

def add_points_good(current_points):
    return current_points + 10 # 関数内は引数の処理だけに集中し、外の世界を傷つけない

# 外側の主導権を持ったラインで、安全に再代入を行う(globalが不要で明快!)
user_points = add_points_good(user_points)
print(user_points) # 結果: 60
Q: 関数が何重にも入れ子(ネスト)になっている状況で、「一番外側」ではなく「1つ親の階層の関数」にある変数を書き換えたいときも `global` を使いますか?
A: いいえ、そこには別の専用キーワードが存在します。global は、いかなる深さからであっても、ファイルを貫通して最外層の「モジュール直下の変数」に繋ぐための命令です。そうではなく、「関数の中にある関数の、そのさらに親の関数」という1つ外側の階層の変数をロックオンしたい場合は、global ではなく nonlocal という別の予約語を使用しなければならないルールになっています。

まとめ

global は、関数の壁を強引に破壊して最外層のグローバルスコープにあるデータを直接書き換えるための強力な予約語です。

  • 関数内部からグローバル変数に対して「値の代入・変更」を加えて同期させる際に宣言が必須となる。
  • 宣言を怠ったまま代入を試みると、関数内限定の同姓同名のローカル変数が独立生成され、外側への書き換え要求は完全に無視される。
  • コード全体の可読性と、不意なデータ書き換えバグを防ぐため、実務での利用は共通設定ファイルの読み込みなど最低限の局面に絞り、基本は引数と return を中心としたクリーンな設計を意識する。

スコープの境界線システムを正確に統治し、global に依存しない頑丈で美しい条件ロジックを組み立てられるようになりましょう。