Pythonのnonlocalによるネストされた関数内での変数変更をわかりやすく解説

スポンサーリンク
スポンサーリンク

nonlocalの概要

ネストされた関数内での変数変更 Python予約語

nonlocal

概要 nonlocal は、ネストされた関数(関数の中に定義された関数)内で外側の関数の変数を変更するために使用されるキーワードです。グローバル変数ではなく、ローカルスコープの変数を操作できる点が特徴です。

わかりやすく説明 nonlocal を使うと、「関数の中の関数から、外側の関数で定義された変数を変更する」ことができます。例えば、カウンターを持つ関数を定義するときに役立ちます。

  • nonlocal はネストされた関数の中から外側の関数の変数を変更できます。
  • グローバル変数ではなく、関数内のスコープにある変数を操作する際に使用します。
  • global とは異なり、関数の外部(グローバルスコープ)の変数には影響を与えません。

nonlocalの基本的な使い方

以下の例では、nonlocal を使って外側の関数の変数 count を更新しています。

# nonlocal を使った例
def outer():
    count = 0  # 外側の関数の変数

    def inner():
        nonlocal count
        count += 1  # 外側の変数を更新
    
    inner()
    print(count)  # 1

outer()
  • inner() 内で nonlocal count を指定。
  • count の値を変更すると、outer() のスコープにある count に影響を与えます。

nonlocalがない場合の挙動

nonlocal を使わずに変数を変更しようとすると、新しいローカル変数が作られてしまい、外側の変数に影響を与えません。

# nonlocal を使わない場合
def outer():
    count = 0  # 外側の関数の変数

    def inner():
        count = 1  # 新しいローカル変数が作成される(外側の変数は変更されない)

    inner()
    print(count)  # 0 (変化なし)

outer()
  • inner() 内で count = 1 を代入すると、新しいローカル変数 count が作成されます。
  • そのため、外側の count は変更されません。

nonlocalを使ったクロージャの作成

nonlocal を使うと、クロージャ(関数内関数が外側の変数を記憶する仕組み)を作成できます。

# nonlocal を使ったカウンター関数
def counter():
    count = 0

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

    return increment

count_up = counter()
print(count_up())  # 1
print(count_up())  # 2
print(count_up())  # 3
  • counter()countincrement() 内で変更可能。
  • 呼び出しのたびに count の値が保持され、増加していきます。

nonlocalの応用例(設定値の更新)

外側の関数で設定された値を、内側の関数から変更する例です。

# 設定値の変更
def config():
    mode = "light"  # デフォルト設定

    def set_mode(new_mode):
        nonlocal mode
        mode = new_mode
        print(f"モード変更: {mode}")

    return set_mode

change_mode = config()
change_mode("dark")  # モード変更: dark
change_mode("light")  # モード変更: light
  • 最初は mode = "light" に設定。
  • set_mode()mode を変更可能。

nonlocalの注意点

  • グローバル変数には影響を与えない: nonlocal は関数内のスコープでしか使えません。
  • 外側の関数が存在しないと使えない: nonlocal を使うには、必ずネストされた関数の中で定義する必要があります。
  • 過度に使うと可読性が低下: 関数が深くネストされると、どの変数が変更されるのか把握しにくくなります。

nonlocalのよくある質問

Q: nonlocal と global の違いは?
A: nonlocal は外側の関数の変数を変更し、global はスクリプト全体のグローバル変数を変更します。
Q: nonlocal はどこで使うのが適切?
A: クロージャや関数内で状態を保持する場合に有用です。
Q: outer 関数内にない変数を nonlocal で操作できますか?
A: できません。必ず外側の関数内で定義された変数にのみ適用されます。

まとめ

nonlocal は、ネストされた関数内から外側の関数の変数を変更するためのキーワードです。

  • 関数内のスコープで、外側の変数を変更できます。
  • クロージャや状態管理に役立ちます。
  • global とは異なり、グローバル変数には影響を与えません。

適切に nonlocal を活用し、柔軟な関数設計を行いましょう。