MeWrite Docs

UnboundLocalError: グローバル変数の再代入で発生するエラー

概要

Pythonで関数内からグローバル変数を参照した後に再代入しようとすると、UnboundLocalError: cannot access local variable 'x' where it is not associated with a value が発生する。Pythonは関数内で変数への代入文があると、その変数を関数スコープ全体でローカル変数として扱うため、代入前の参照がエラーになる。

エラーメッセージ

Traceback (most recent call last):
  File "example.py", line 8, in <module>
    increment()
  File "example.py", line 5, in increment
    print(counter)
          ^^^^^^^
UnboundLocalError: cannot access local variable 'counter' where it is not associated with a value

Python 3.12以前では以下のメッセージになる:

UnboundLocalError: local variable 'counter' referenced before assignment

原因

  1. 関数内でのグローバル変数への再代入: Pythonのスコープルールにより、関数内に x = ... という代入文があると、その関数全体で x はローカル変数として扱われる。代入文より前に x を参照すると、まだ値が束縛されていないローカル変数を読み取ることになりエラーとなる。

  2. 複合代入演算子(+=, -= など)の使用: counter += 1counter = counter + 1 と等価であり、右辺の counter の読み取り時点でローカル変数がまだ未束縛のためエラーとなる。

  3. 条件分岐内での代入: if ブロック内でのみ変数を代入し、else ブロックや後続コードで参照する場合、条件が成立しなかったパスでUnboundLocalErrorが発生する。

解決策

1. global宣言を使う

関数内でグローバル変数を変更する場合、global 宣言を関数の先頭に記述する。

1
2
3
4
5
6
7
8
9
counter = 0

def increment():
    global counter
    print(counter)  # 読み取り可能
    counter += 1    # 書き込み可能

increment()
print(counter)  # 1

2. 引数と戻り値で受け渡す(推奨)

global の多用は可読性を下げる。関数の引数と戻り値で値を受け渡す設計が望ましい。

1
2
3
4
5
6
7
8
counter = 0

def increment(value):
    value += 1
    return value

counter = increment(counter)
print(counter)  # 1

3. nonlocalを使う(ネストされた関数)

クロージャ内で外側の関数の変数を変更する場合は nonlocal を使用する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def outer():
    count = 0

    def inner():
        nonlocal count
        count += 1
        return count

    print(inner())  # 1
    print(inner())  # 2

outer()

4. ミュータブルなオブジェクトを使う

リストや辞書などのミュータブルオブジェクトは、参照自体の再代入ではなく内容の変更であれば global 宣言なしでも可能。

1
2
3
4
5
6
7
8
state = {"counter": 0}

def increment():
    # 辞書の中身を変更(再代入ではない)
    state["counter"] += 1

increment()
print(state["counter"])  # 1

5. 条件分岐での未束縛を防ぐ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# NG: 条件が偽のとき result が未定義
def check(value):
    if value > 0:
        result = "positive"
    return result  # UnboundLocalError(value <= 0 のとき)

# OK: デフォルト値を設定
def check(value):
    result = "non-positive"  # デフォルト値
    if value > 0:
        result = "positive"
    return result

関連エラー

関連エラー

python の他のエラー

最終更新: 2026-03-20