pythonクロージャーを最初から知ってください

閉鎖とは何ですか?クロージャーの用途は何ですか?なぜクロージャーを使用するのですか?今日は、これら3つの質問に答えて、閉鎖を段階的に理解します。

クロージャーと関数は密接に関連しています。クロージャーを導入する前に、ネストされた関数の概念や変数のスコープなど、いくつかの背景知識を導入する必要があります。

範囲

スコープは、プログラムの実行中に変数にアクセスできるスコープです。関数で定義された変数はローカル変数です。ローカル変数のスコープは、関数のスコープ内にのみ含めることができ、関数の外部で参照することはできません。

モジュールの最外層で定義されている変数はグローバル変数であり、グローバルスコープに表示されます。もちろん、グローバル変数は関数で読み取ることもできます。

例えば:

num = 10 # 全局作用域变量
def foo():
    print(num)  # 10

関数の外部からローカル変数にアクセスすることはできません。
例えば:

def foo():
    num = 10
print(num)  # NameError: name 'num' is not defined

ネストされた機能

関数は、モジュールの最外層だけでなく、別の関数でも定義できます。関数で定義された関数は、ネストされた関数と呼ばれます。次に例を示します。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def print_msg():
    # print_msg 是外围函数
    msg = "zen of python"

    def printer():
        # printer是嵌套函数
        print(msg)
    printer()
# 输出 zen of python
print_msg()

ネストされた関数の場合、外部スコープで宣言された非ローカル変数にアクセスできます。たとえば、コード例の変数msgには、ネストされた関数プリンターから通常どおりアクセスできます。

では、関数自体のスコープ外でもローカル変数にアクセスできる可能性はありますか?答えは閉鎖です

閉鎖とは何ですか

ファーストクラスのオブジェクトとして、関数を関数の戻り値として返すことができます。次に、次の例を考えてみましょう。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def print_msg():
    # print_msg 是外围函数
    msg = "zen of python"
    def printer():
        # printer 是嵌套函数
        print(msg)
    return printer

another = print_msg()
# 输出 zen of python
another()

このコードは前の例とまったく同じ効果があり、「zenofpython」も出力します。違いは、内部機能プリンターが戻り値として直接戻ることです。

通常、関数内のローカル変数は、関数の実行中にのみ使用できます。print_msg()が実行されると、msg変数は使用できなくなると考えられます。ただし、ここでは、print_msgの実行後、通常、別の変数が呼び出されたときにmsg変数の値が出力されることがわかります。これはクロージャーの関数であり、関数の外部でローカル変数にアクセスできるようにします。

この例を読んだ後、クロージャーを定義しましょう。ウィキペディアの説明は次のとおりです。

コンピュータサイエンスでは、ClosureはLexical Closureの略で、自由変数を参照する関数です。参照された空き変数は、それが作成された環境を離れた場合でも、この関数とともに存在します。したがって、クロージャは関数とそれに関連する参照環境で構成されるエンティティであるという別の見方があります。

もう1つはクロージャーです。クロージャーは本質的に関数であり、プリンター関数と変数msgの2つの部分で構成されています。クロージャーは、これらの変数の値を常にメモリに保持します。

クロージャーは、その名前が示すように、クラスで定義された属性値と同じように、フリー変数でラップされたクローズドパッケージです。フリー変数の表示範囲にはパッケージが付属しています。このパッケージにアクセスできる場所から、この自由にアクセスできます。変数。

クロージャーを使用する理由

クロージャーは、グローバル変数の使用を回避します。さらに、クロージャーを使用すると、関数を操作する特定のデータ(環境)に関連付けることができます。これは、オブジェクト指向のプログラミングと非常によく似ています。オブジェクト指向のプログラミングでは、オブジェクトを使用して、特定のデータ(オブジェクトプロパティ)を1つ以上のメソッドに関連付けることができます。

一般的に、オブジェクトにメソッドが1つしかない場合は、クロージャーを使用することをお勧めします。
例を見てみましょう:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def adder(x):
    def wrapper(y):
        return x + y
    return wrapper

adder5 = adder(5)
# 输出 15
adder5(10)
# 输出 11
adder5(6)

これは、クラスを使用するよりもエレガントです。さらに、デコレータは、クロージャに基づくアプリケーションシナリオでもあります。

すべての関数には__closure__属性があります。この関数がクロージャーの場合、セルオブジェクトで構成されるタプルオブジェクトを返します。セルオブジェクトのcell_contentsプロパティは、クロージャー内の自由変数です。

>>> adder.__closure__
>>> adder5.__closure__
(<cell at 0x103075910: int object at 0x7fd251604518>,)
>>> adder5.__closure__[0].cell_contents
5

これは、ローカル変数関数から離れた後、のクロージャーcell_contents格納されているため、関数の外部からもアクセスできる理由を説明しています。

おすすめ

転載: blog.csdn.net/sinat_38682860/article/details/109311643