Python | 関数:スコープ

Python
スポンサーリンク

概要(スコープは「変数が見える範囲」)

スコープとは「変数や関数がどこから参照できるか」を決めるルールです。Python では ローカルスコープ(関数の中)、グローバルスコープ(ファイル全体)、さらに 組み込みスコープ(Pythonが最初から持っている関数や定数)があります。スコープを理解すると「変数が見えない」「意図せず上書きされた」といった初心者の典型的なバグを防げます。

x = 10  # グローバル変数

def func():
    y = 5  # ローカル変数
    print(x, y)

func()  # 10 5
print(y)  # エラー!関数の外からは見えない
Python

ローカルスコープ(関数の中だけ有効)

関数内で作られた変数は外から見えない

関数の中で定義した変数は「ローカル変数」と呼ばれ、その関数の外からは参照できません。これにより、関数ごとに独立した“箱”を持てるので、他の処理と干渉しません。

def greet():
    name = "Hanako"
    print("Hello", name)

greet()
# print(name)  # NameError: name is not defined
Python

ローカル変数は呼び出しのたびに新しく作られる

関数を呼ぶたびにローカル変数は新しく生成され、終了すると消えます。だから「前回の値が残っている」ということはありません。

def counter():
    n = 0
    n += 1
    print(n)

counter()  # 1
counter()  # 1(毎回リセットされる)
Python

グローバルスコープ(ファイル全体で有効)

グローバル変数はどこからでも見える

関数の外で定義した変数は「グローバル変数」。関数の中からも参照できます。ただし、書き換えは注意が必要です。

x = 10

def show():
    print(x)  # グローバル変数を参照

show()  # 10
Python

グローバル変数を書き換えるには global 宣言が必要

関数の中でグローバル変数を変更したい場合は、global を明示しないと「新しいローカル変数」として扱われてしまいます。

count = 0

def inc():
    global count
    count += 1

inc()
print(count)  # 1
Python

ただし、グローバル変数の書き換えはバグの原因になりやすいので、基本は「引数と返り値」でデータをやり取りする方が安全です。

ネストスコープと LEGB ルール(重要ポイントの深掘り)

LEGB ルールとは

Python は変数を探すときに L → E → G → B の順で探します。

  • L (Local): 関数内のローカル変数
  • E (Enclosing): 外側の関数のスコープ(ネストした関数)
  • G (Global): ファイル全体の変数
  • B (Built-in): Pythonが最初から持っている関数や定数(len, print など)
x = "global"

def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print(x)
    inner()

outer()  # "local"
Python

nonlocal で「外側の関数の変数」を操作する

ネストした関数で「外側の関数の変数」を変更したい場合は nonlocal を使います。

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

f = outer()
print(f())  # 1
print(f())  # 2
Python

これで「外側の関数の変数を保持し続ける」仕組みが作れます。クロージャの基礎です。

実務での設計指針(スコープを正しく使う)

グローバル変数は最小限に

グローバル変数は便利ですが、複数の関数から書き換えられると予期せぬバグが起きます。設定値や定数に限定し、処理のデータは引数と返り値で渡しましょう。

ローカル変数で「関数の独立性」を保つ

関数内で完結する変数はローカルに閉じ込めることで、他の処理に影響を与えません。テストや再利用がしやすくなります。

クロージャやクラスで「状態を保持」

「関数を呼ぶたびに前回の値を覚えておきたい」なら、nonlocal を使ったクロージャか、クラスのインスタンス変数を使うのが定石です。

例題で身につける(定番から一歩先まで)

例題1:ローカル変数とグローバル変数の違い

x = 100  # グローバル

def demo():
    x = 50  # ローカル
    print("関数内:", x)

demo()
print("関数外:", x)
# 関数内: 50
# 関数外: 100
Python

例題2:global を使ったカウンタ

count = 0

def inc():
    global count
    count += 1

inc()
inc()
print(count)  # 2
Python

例題3:nonlocal を使ったクロージャ

def make_counter():
    n = 0
    def inc():
        nonlocal n
        n += 1
        return n
    return inc

c = make_counter()
print(c())  # 1
print(c())  # 2
Python

例題4:LEGB ルールの確認

x = "global"

def outer():
    x = "enclosing"
    def inner():
        print(x)  # enclosing が参照される
    inner()

outer()
Python

まとめ

  • スコープは「変数が見える範囲」。Python は LEGB ルールで変数を探す。
  • ローカル変数は関数内だけ有効、グローバル変数はファイル全体で有効。
  • global でグローバルを書き換え、nonlocal で外側の関数の変数を書き換える。
  • グローバル変数は最小限にし、引数と返り値でデータを渡す設計が安全。
  • スコープを理解すると「変数が見えない」「意図せず上書きされた」といった初心者の典型的なバグを防げる。

これをマスターすれば、あなたのコードは「安全で予測可能な動き」をするようになり、プロのプログラマーに一歩近づけます。

タイトルとURLをコピーしました