変数のスコープ、ローカル変数とグローバル変数
記事の内容
この記事では、Pythonにおける変数の有効範囲(スコープ)について説明します。プログラムのサイズが大きくなってくると、プログラム全体で変数名を管理することが難しくなってきます。このため、Pythonの変数にはスコープがあり、スコープの中でのみ変数を管理すれば良いようになってます。
***わからない用語があるときは索引ページへ***
1.ローカル変数の有効範囲
Pythonの場合、関数の中で生成された変数は、後ろで説明するグローバル変数宣言をしない限り、生成された関数の中でのみ有効です。生成された関数の中でのみ有効な変数を、ローカル変数と呼びます。
この変数の有効範囲のことを、変数のスコープとも呼びます。スコープ外で同じ変数名の変数を生成しても、全く別の変数として扱われます。
サンプルプログラムで動きをみてみましょう。
##func_ex2_1.py
##関数の定義
def tashizan(x, y):
result = x + y
return result
##実行開始位置
result = 5
wa = tashizan(3, 5)
print("3 + 5 =", wa)
print("スコープ外のresultは書き換わらない-> result =", result)
関数tashizanの中で生成された変数resultと、関数の外の最上位のプログラムブロックで生成されたresultは、変数のスコープが異なります。変数名はresultで同じですが、別の変数として扱われます。
最上位プログラムブロックで生成された変数resultは、tashizanのローカル変数resultに演算結果が代入されても、書き換わっていません。
出力結果
3 + 5 = 8
スコープ外のresultは書き換わらない-> result = 5
def部のプログラムブロックの中で宣言される、引数を渡される変数は、関数のローカル変数として扱われます。すなわち、"def tashizan(x, y):"のx, yは関数"tasizan"のローカル変数となります。
2.グローバル変数を使う
プログラム全体で変数を使いたい場合もあります。
プログラム全体で共有する変数のことを、グローバル変数と呼びます。グローバル変数を利用する場合は、関数の中で利用するグローバル変数を宣言する必要があります。宣言の仕方は、
global <グローバル変数名>
です。サンプルプログラムで確認しましょう。
##func_ex2_2.py
def print_var():
global x
##xとyに値を代入して出力
x = 5
y = 10
print("グローバル変数x =", x)
print("ローカル変数y =", y)
print("\n")
##プログラム実行開始位置
##xとyに初期値を代入し、出力
x = 1
y = 1
print("xの初期値:", x)
print("yの初期値:", y)
print("\n")
##関数を実行
print_var()
##関数実行後の変数xとyを出力
print("関数実行後のxの値:", x)
print("関数実行後のyの値:", y)
関数print_varの中でグローバル変数宣言したxだけ値が書き換わっていることがわかると思います。
出力結果
xの初期値: 1
yの初期値: 1
グローバル変数x = 5
ローカル変数y = 10
関数実行後のxの値: 5
関数実行後のyの値: 1
3.最上位ブロックの変数はグローバル変数
最上位のプログラムブロックで生成される変数は、グローバル変数です。"func_ex2_3.py"のprint_var関数では、変数xを生成していないのに出力しています。ここで出力しているxは、最上位ブロックで生成されたグローバル変数xを出力しているのです。
##func_ex2_3.py
def print_var():
print("x =", x)
##プログラム実行開始位置
x = 3
print_var()
出力結果
x = 3
4.グローバル変数とローカル変数の優先順位
関数の中で、グローバル変数名と同じ変数名のローカル変数が生成された場合は、その変数はローカル変数として扱われます。この場合、変数名は同じでも、グローバル変数とは別のローカル変数となります。関数の中でグローバル変数をグローバル変数として扱う場合についても、上記2.で説明したとおりにグローバル変数を宣言する必要があります。
上述の"func_ex2_1.py"の変数resultは、最上位のプログラムブロックで生成されているため、グローバル変数です。しかし、関数tashizanの中で、同じ変数名のローカル変数resultが生成されたため、tashizanのresultはローカル変数として扱われています。その結果、global変数のresultとは変数名は同じでも、別の変数として扱われます。
関数tashizanで出力されたresultと、最上位ブロックで出力されたresultの値を見ると、両者が別の変数であることがわかると思います。