関数のネスト定義からPython閉パッケージへ


文書ディレクトリ
  • 一、ネスト関数
  • を定義する
  • 二、閉包関数
  • を定義する
  • 三、閉包形成条件
  • 四、いつ閉包
  • を使用するか
  • 五、閉包特性拾遺
  • この文書では、次のことを説明します.
  • Python閉鎖とは何ですか?
  • Python閉パッケージをどのように定義しますか?
  • なぜPythonの閉パッケージを使うのですか?

  • 一、ネスト関数の定義
    Python閉包とは何かを知る前に,ネスト関数とは何かをまず理解する必要がある.
  • ネスト関数:1つの関数(外部関数)の内部で定義された関数をネスト関数と呼びます.ネスト関数は外部関数で定義された変数にアクセスできます.
  • たとえば、次のコードでは、ネストされた関数で非ローカル変数にアクセスする方法を示します.
    def print_msg(msg):
        #       
    
        def printer():
            #       
            print(msg)
    
        printer()
    
    
    #     ,  "Hello"
    print_msg("Hello")
    
    

    二、閉包関数の定義
    上記の例ではprint_を変更するとmsg()関数の最後の行で、関数呼び出しprinter()を関数名printerに戻すように変更するとどうなりますか?次のコードを実行します.
    def print_msg(msg):
        #       
    
        def printer():
            #       
            print(msg)
    
        return printer
    
    
    foo = print_msg("Hello")
    
    del print_msg
    
    foo()
    
    

    上記のコードの実行結果は、以下の理由で「Hello」のままです.
  • print_を呼び出すmsg()関数の入力パラメータ「Hello」;
  • print_msg()関数の戻り値は変数fooに与えられ、printer()関数オブジェクトが保存する空間を指す.
  • 関数print_msg()の実行が完了すると、msg変数はメモリに保存されます(delキーを使用して関数が明示的に削除されます).
  • 次のようになります.
    閉包はPythonの言語特性であり、この特性はいくつかのデータ(msg)とコード(ネスト関数)を結合させることができる.
    三、閉包形成条件
    上記のコードから分かるように、Pythonでは、ネストされた関数が外部関数に定義された非局所変数を参照すると、閉パケットが形成される.
    より厳密には、閉パッケージを形成するには、以下の3つの条件が必要です.
  • にはネスト関数が必要です.
  • ネスト関数は、外部関数に定義された非局所変数を使用する.
  • 外部関数の戻り値は、ネストされた関数の名前でなければなりません.

  • 四、いつ閉包を使うか
    クローズド・パッケージは、グローバル変数の過剰使用を回避し、ある程度のデータ非表示を提供します.また、クローズド・パッケージは、ある問題にクラス・オブジェクト向けのソリューションを提供することもできます.
    最も重要なのは、オブジェクト向けに需要を実現する場合、実現するインスタンスメソッドが少ない場合がある.この場合、パッケージを閉じると、より優雅でメモリを節約できる(クラスをカスタマイズするとobjectクラスのメソッドが最も継承されるため、カスタムクラスをインスタンス化する場合、必要なメモリが大きい)ソリューションが提供されます.ただし、カスタムクラスの属性とメソッドが多い場合は、クラスを定義することが望ましいです.
    たとえば、指定した倍数に任意の数を乗算する需要があります.
    (1)オブジェクト指向方式を使用する:
    class Multiplier(object):
    
        def __init__(self, multiple):
            self.multiple = multiple
    
        #     callable     Multiplier       ,
        # __call__       
        def __call__(self, *args, **kwargs):
            print(args[0] * self.multiple)
    
    
    multiplier3 = Multiplier(3)
    multiplier3(5)
    
    multiplier5 = Multiplier(5)
    multiplier5(7)
    
    

    (2)閉パッケージの使用方法:
    def make_multiplier_of(multiple):
    
        def multiplier(num):
            return num * multiple
    
        return multiplier
    
    
    # 3   
    times3 = make_multiplier_of(3)
    
    # 5   
    times5 = make_multiplier_of(5)
    
    print(times3(5))
    
    print(times5(7))
    
    print(times5(times3(2)))
    
    

    五、閉包特性ピックアップ
    実際、すべての関数には1つの__があります.closure__関数が閉パッケージ関数である場合、この属性はセルオブジェクト(cell object)を含むセルグループであり、そうでない場合はNoneであり、各セルオブジェクトのcell_contents属性により、閉パッケージに格納されている非局所変数値を以下のコードで示すように取得することができる.
    def foo_outer(argv):
        var = 100
    
        def foo_inner():
            print(argv + var)
    
        return foo_inner
    
    
    foo = foo_outer(200)
    foo()
    print(foo_outer.__closure__)
    print(foo.__closure__)
    print("foo.__closure__[0].cell_contents = ", foo.__closure__[0].cell_contents)
    print("foo.__closure__[1].cell_contents = ", foo.__closure__[1].cell_contents)
    
    

    上記のコードの実行結果は次のとおりです.
    300 None (, ) foo.__closure__[0].cell_contents = 200 foo.__closure__[1].cell_contents = 100
    nonlocalキーワード:一般的に、ネスト関数は外部関数で定義された変数(非ローカル変数と呼ばれる)にのみアクセスでき、変更できません.非ローカル変数を変更する必要がある場合は、ネスト関数で非ローカル変数をnonlocalキーワードで明示的に宣言する必要があります.