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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 第一級関数
- クロージャと自由変数
- nonlocalと可変状態
- 部分関数