亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

閉鎖

Python クロージャを紹介する記事はインターネット上に多數(shù)ありますが、この記事では要件問題を解きながらクロージャについて學びます。

この要件は次のようなもので、學習時間を分単位で記録し続ける必要があります。例えば、2分勉強したら2を返し、しばらくして10分勉強したら12を返し、このように學習時間が積み重なっていきます。

この要求に直面して、私たちは通常、時間を記録するためのグローバル変數(shù)を作成し、各學習時間を追加するメソッドを使用します。これは通常、次の形式で記述されます。

time = 0
def insert_time(min):
    time = time + min
    return  time
print(insert_time(2))
print(insert_time(10))

真剣に考えるそれ、何か問題はありますか?

実際には、これは Python でエラーを報告します。次のエラーが報告されます:

UnboundLocalError: local variable 'time' referenced before assignment

これは、Python では、関數(shù)がグローバル変數(shù)と同じ名前を使用して変數(shù)の値を変更すると、その変數(shù)はローカル変數(shù)になり、これにより、定義せずに関數(shù)內で參照することになるため、このエラーが報告されます。

本當にグローバル変數(shù)を參照して関數(shù)內で変更したい場合は、どうすればよいでしょうか?

global キーワードを使用できます。具體的な変更は次のとおりです:

time = 0
def insert_time(min):
    global  time
    time = time + min
    return  time
print(insert_time(2))
print(insert_time(10))

出力結果は次のとおりです:

2
12

ただし、ここではグローバル変數(shù)が使用されています。開発中は最善を盡くします。グローバル変數(shù)の使用はできるだけ避けてください。さまざまなモジュールやさまざまな関數(shù)がグローバル変數(shù)に自由にアクセスできるため、グローバル変數(shù)は予測できない場合があります。たとえば、プログラマ A がグローバル変數(shù) time の値を変更し、次にプログラマ B も time を変更すると、エラーがあった場合、そのようなエラーを見つけて修正するのは困難です。

グローバル変數(shù)により、関數(shù)またはモジュール間の汎用性が低下します。さまざまな関數(shù)またはモジュールがグローバル変數(shù)に依存します。同様に、グローバル変數(shù)はコードの可読性を低下させ、読者は呼び出される特定の変數(shù)がグローバル変數(shù)であることを認識しない可能性があります。

もっと良い方法はありますか?

現(xiàn)時點では、クロージャを使用して問題を解決しています。コードを直接見てみましょう:

time = 0
def study_time(time):
    def insert_time(min):
        nonlocal  time
        time = time + min
        return time
    return insert_time
f = study_time(time)
print(f(2))
print(time)
print(f(10))
print(time)

出力結果は次のとおりです:

2
0
12
0

最も直接的な表現(xiàn)ここにグローバル変數(shù) time があります。これまでのところ、最終的には変更されていません。nonlocal キーワードはここでもまだ使用されており、関數(shù)または他のスコープでの外部 (非グローバル) 変數(shù)の使用を示しています。では、上記のコードの具體的な実行プロセスは何でしょうか。以下の図を見てみましょう:

a4e16c80e1df62cb932f66f1b8b91c9.png

外部関數(shù)のローカル スコープ內の変數(shù)が內部関數(shù)のローカル スコープでアクセスできるこの種の動作クロージャと呼ばれます。より直接的に表現(xiàn)すると、関數(shù)がオブジェクトとして返されるときに外部変數(shù)が含まれ、クロージャが形成されます。 k

クロージャはグローバル変數(shù)の使用を回避し、さらにクロージャを使用すると、関數(shù)をその動作対象のデータ (環(huán)境) に関連付けることができます。また、クロージャを使用すると、コードをよりエレガントにすることができます。また、次の記事で説明するデコレータもクロージャに基づいて実裝されています。

ここで質問になりますが、これは閉鎖だと思いますか、それとも閉鎖だと思いますか?この関數(shù)がクロージャであることを確認する方法はありますか?

はい、すべての関數(shù)には __closure__ 屬性があります。関數(shù)がクロージャの場合、セルで構成されるタプル オブジェクトを返します。 cell オブジェクトの cell_contents プロパティは、クロージャに格納される変數(shù)です。

これを印刷して體験してみましょう:

time = 0
def study_time(time):
    def insert_time(min):
        nonlocal  time
        time = time + min
        return time
    return insert_time
f = study_time(time)
print(f.__closure__)
print(f(2))
print(time)
print(f.__closure__[0].cell_contents)
print(f(10))
print(time)
print(f.__closure__[0].cell_contents)

印刷結果は次のとおりです:

(<cell at 0x0000000000410C48: int object at 0x000000001D6AB420>,)
2
0
2
12
0
12

印刷結果から、渡された値は常に次の場所に格納されていることがわかります。クロージャの cell_contents です。これがクロージャの最大の機能であり、親関數(shù)の変數(shù)を內部定義された関數(shù)にバインドできます。クロージャを生成した親関數(shù)が解放された場合でも、クロージャはまだ存在します。

クロージャのプロセスは、実際にはクラス (親関數(shù)) がインスタンス (クロージャ) を生成するのと似ています。違いは、親関數(shù)は呼び出されたときにのみ実行されることです。実行後、その環(huán)境は解放されますが、クラスはファイル內で実行されます。クラスはその時に作成され、スコープは通常、プログラムの実行後に解放されます。そのため、再利用する必要があり、クラスとして定義できない一部の関數(shù)については、クロージャを使用した方が占有するリソースが少なくなります。クラスを使用するよりも軽量で柔軟です。

學び続ける