ホームページ >バックエンド開発 >Python チュートリアル >入れ子になった Python 関数が定義時ではなく実行時に変数にアクセスするのはなぜですか?

入れ子になった Python 関数が定義時ではなく実行時に変数にアクセスするのはなぜですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-24 13:27:30890ブラウズ

Why Do Nested Python Functions Access Variables at Execution Time, Not Definition Time?

入れ子関数とローカル変数へのアクセス

Python では、入れ子関数は、それを囲んでいるスコープからローカル変数にアクセスできます。ただし、このアクセスのタイミングは直観に反している可能性があります。

次のコード スニペットを考えてみましょう:

class Cage(object):
    def __init__(self, animal):
        self.animal = animal

def gotimes(do_the_petting):
    do_the_petting()

def get_petters():
    for animal in ['cow', 'dog', 'cat']:
        cage = Cage(animal)

        def pet_function():
            print "Mary pets the " + cage.animal + "."

        yield (animal, partial(gotimes, pet_function))

funs = list(get_petters())

for name, f in funs:
    print name + ":",
    f()

メアリーが各動物を撫でるという期待される出力を取得する代わりに、出力には「メアリーがペットを撫でる」と表示されます。 3 匹の動物すべてに対して「猫」。この動作は、ネストされた関数 pet_function が定義時ではなく実行時にローカル変数ケージを検索するために発生します。

関数 get_petters が呼び出されると、ローカル変数ケージが各動物に順次割り当てられます。ループ内で。ただし、関数の終わりまでに、cage には最後の値 ('cat') が含まれます。 get_petters によって返される関数が呼び出されると、それらはすべて、値 'cat' を持つ同じケージ変数にアクセスします。

この問題に対処するには、次のようなさまざまな手法を使用できます。

  • バインドされたケージで部分関数を使用する変数:

    from functools import partial
    
    def pet_function(cage):
      print "Mary pets the " + cage.animal + "."
    
    yield (animal, partial(gotimes, partial(pet_function, cage=cage)))
  • ネストされた関数の新しいスコープの作成:

    def scoped_cage(cage):
      def pet_function():
          print "Mary pets the " + cage.animal + "."
      return pet_function
    
    yield (animal, partial(gotimes, scoped_cage(cage)))
  • 変数をデフォルト値としてバインドキーワードパラメータ:

    def pet_function(cage=cage):
      print "Mary pets the " + cage.animal + "."
    
    yield (animal, partial(gotimes, pet_function))

以上が入れ子になった Python 関数が定義時ではなく実行時に変数にアクセスするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。