ProgrammingPythonエンジニア

Pythonはネストされた関数(クロージャ)のメカニズムをどのように実装していますか?クロージャはどのように使用され、注意すべき点は何ですか?外部関数の変数を正しく変更する方法はどれですか?

Hintsage AIアシスタントで面接を突破

回答。

Pythonにおけるクロージャ(closure)は、外部変数の値を「記憶」する関数であり、たとえそれがスコープの外で呼び出されても、その値を保持します。クロージャは、内部関数が外部関数で定義された変数を参照するときに作成されます。Python 3では、ネストされた関数からこれらの変数を変更するために、nonlocalキーワードを使用します。

例:

def make_accumulator(): total = 0 def add(value): nonlocal total total += value return total return add acc = make_accumulator() print(acc(10)) # 10 print(acc(5)) # 15

nonlocalがないと、変数totalは変更できない(UnboundLocalErrorエラー)。

トリッキーな質問。

質問: 「内部関数からnonlocalなしで外部関数の変数を増加させることはできますか?」

回答: いいえ、nonlocalなしでは、エラーが発生します。なぜなら、インタプリタはその変数を内部関数のローカルと見なすからです。例:

def outer(): count = 0 def inner(): count += 1 # UnboundLocalErrorエラー return count return inner

このテーマの詳細を知らないために実際に起こったエラーの例。


物語 あるウェブアプリケーションで、ネストされた関数を通じて各ハンドラのローカルカウンタを実装しようとしましたが、nonlocalを使用するのを忘れました。その結果、カウンタは常に1を返し、外部クロージャとは無関係なローカル空間でcountをカウントしていました。


物語 マルチスレッドの問題では、クロージャやラムダを頻繁に使用します。クロージャを理解していなかったため、すべてのラムダ関数がループ変数の最後の値を「記憶」し、タスクを異なるものとして処理する代わりに互いにコピーしました。


物語 デコレーターを正しいクロージャなしで書いたため(外部スコープにパラメータを渡さなかった)、デコレーターが呼び出し間で状態を保持できないという状況が発生し、予期しない結果とアプリケーションの不安定な動作を引き起こしました。