グローバル変数とローカル変数

次のプログラムを実行すればどのように出力されるでしょうか。

x = 1

def foo():
    x = 2
    print(x)

foo()
print(x)

答えは次の通りです。

2
1

関数の外で定義された x = 1 はグローバル変数で、プログラム全体で有効です。これに対して、関数の中で定義された x = 2 はローカル変数で、関数の中でしか有効でありません。両者はまったく別物なので、関数の中でローカル変数に代入しても、グローバル変数は変わりません。

関数の中でグローバル変数を使うには、次のようにします。

x = 1

def foo():
    global x
    x = 2
    print(x)

foo()
print(x)

この出力は次の通りです。

2
2

関数の中の x はグローバル変数になり、関数の外のものと同じものになりました。

次はどうでしょうか。

x = 1

def foo():
    print(x)

foo()
print(x)

この出力は次の通りです。

1
1

関数の中で global x しませんでしたが、この場合は関数の中では x を参照しているだけですので、グローバルの x の値を出力します。

では、次はどうでしょうか。

x = 1

def foo():
    print(x)
    x = 2

foo()
print(x)
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value

エラーになってしまいました。これは関数の中で x の値を変えようとしたため、関数全体で x がローカル変数になり、関数の中で print(x) した時点ではローカル変数に値が入っていないので、エラーになったのです。

これは気をつけないといけないバグの元で、特に

x = 1

def foo():
    print(x)
    # ほかの処理
    # ほかの処理
    x = 2

のようにずっと後の方で代入してしまった場合にも、遡って関数の最初の print(x) でエラーになるので、注意が必要です。

なお、この例は、「インタプリタは1行ずつ解釈して実行する」という俗説の反例にもなっています。実際には、現代のインタプリタは全部をコンパイルしてから実行しますので、ずっと後の部分が前の部分に影響することがありえます。