0Pricing
Python Academy · レッスン

nonlocalと可変状態

外側のスコープを変更します

「nonlocalと可変状態」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。

外側の変数の読み取りと書き込み

内側の関数は外側の変数を自由に読み取れますが、その名前に代入しようとすると、Pythonは代わりに新しいローカル変数として扱います。これは初心者がよく戸惑う点です。

def outer():
    count = 0
    def inner():
        return count
    return inner()
print(outer())

代入の落とし穴

意図を宣言せずに外側の名前へ代入すると、その名前はローカルになります。そのため外側の変数は更新されず、ここでの変更は失われます。

def outer():
    count = 0
    def bump():
        count = count + 1
    try:
        bump()
    except UnboundLocalError as e:
        print('Error:', e)
outer()

nonlocalキーワード

nonlocalは、ある名前が最も近い外側の関数スコープにある変数を参照することを宣言します。そのため、代入するとローカル変数を新しく作るのではなく、外側の変数が更新されます。

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

カウンタークロージャ

nonlocalを使うと、状態を持つカウンターを構築できます。呼び出すたびにキャプチャされた変数が変更され、進行状況が保持されます。

def make_counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment
c = make_counter()
print(c())
print(c())
print(c())

独立したカウンター

各クロージャが別々の変数をキャプチャするため、各カウンターは独自の状態を保持します。

def make_counter():
    count = 0
    def inc():
        nonlocal count
        count += 1
        return count
    return inc
a = make_counter()
b = make_counter()
print(a(), a(), b())

nonlocalとglobalの違い

nonlocalは外側の関数スコープを対象とし、globalはモジュールレベルを対象とします。クロージャにはnonlocalを、モジュール全体で共有する状態にはglobalを使用します。

total = 0
def add_global(n):
    global total
    total += n
add_global(5)
add_global(3)
print(total)

nonlocalを使わない可変状態

外側の値がリストや辞書のような可変オブジェクトであれば、nonlocalなしでその内容を直接変更できます。これは名前自体を再束縛していないためです。

def make_logger():
    history = []
    def log(msg):
        history.append(msg)
        return history
    return log
log = make_logger()
log('start')
print(log('stop'))

アキュムレーター

nonlocalとクロージャを組み合わせると、受け取った各値を記憶している合計に加算する、累積型のアキュムレーターを作成できます。

def make_accumulator():
    total = 0
    def add(n):
        nonlocal total
        total += n
        return total
    return add
acc = make_accumulator()
print(acc(10))
print(acc(5))
print(acc(100))

シンプルなトグル

nonlocalを使うと、呼び出すたびにブール状態を簡単に切り替えられます。

def make_toggle():
    on = False
    def toggle():
        nonlocal on
        on = not on
        return on
    return toggle
t = make_toggle()
print(t(), t(), t())

状態をリセットする

同じ外側の状態を共有する複数の内側の関数を公開できます。たとえば、一方を加算用、もう一方をリセット用にできます。

def make_bank():
    balance = 0
    def deposit(n):
        nonlocal balance
        balance += n
        return balance
    def reset():
        nonlocal balance
        balance = 0
        return balance
    return deposit, reset
deposit, reset = make_bank()
print(deposit(50))
print(reset())

nonlocalには既存の変数が必要

nonlocalを使うには、対象の名前が外側のスコープにすでに存在している必要があります。存在しない場合、Pythonは定義時にSyntaxErrorを発生させます。新しい外側の変数を作成することはできません。

def outer():
    value = 'set'
    def inner():
        nonlocal value
        value = 'changed'
    inner()
    return value
print(outer())

クイックチェック

ネストした関数内で、外側の関数にある変数を再代入したい場合、どのキーワードを使いますか?

復習:nonlocalと可変状態

まとめ:

  • 外側の名前への代入は通常、新しいローカル変数を作成します。nonlocalはそれを防ぎます。
  • nonlocalは外側の関数スコープを対象とし、globalはモジュールを対象とします。
  • 可変オブジェクトの内容を直接変更する場合、宣言は必要ありません。
  • nonlocalを使ったクロージャにより、状態を記憶するカウンター、アキュムレーター、トグルを構築できます。
def make_counter():
    n = 0
    def inc():
        nonlocal n
        n += 1
        return n
    return inc
c = make_counter()
print(c(), c())

よくある質問

「nonlocalと可変状態」レッスンは無料ですか?

はい。「nonlocalと可変状態」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。

「nonlocalと可変状態」で何を学びますか?

外側のスコープを変更します ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Python Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「nonlocalと可変状態」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPython Academyレッスンでコードを書いて実行できますか?

はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 第一級関数
  2. クロージャと自由変数
  3. nonlocalと可変状態
  4. 部分関数
← Python Academyに戻る