ホームページ  >  記事  >  バックエンド開発  >  Pythonデコレータの詳しい解説

Pythonデコレータの詳しい解説

藏色散人
藏色散人オリジナル
2020-02-13 11:41:204991ブラウズ

Pythonデコレータの詳しい解説

Python デコレータの詳細分析

Python デコレータの詳細分析

何デコレータですか?

推奨学習: Python ビデオ チュートリアル

Python デコレータ (関数デコレータ) は、元の関数の機能を拡張するために使用される関数です。元の関数名(またはクラス名)を変更して、関数に新しい関数を追加します。

この関数の特別な点は、戻り値も関数であるということです。この関数は、「オリジナルの」関数が埋め込まれた関数です。

一般的に言えば、元の関数コードを拡張します。最も直接的な方法は、コードに侵入して変更することです。例:

import time
def f():
    print("hello")
    time.sleep(1)
    print("world")  

これは最もオリジナルな関数であり、合計を記録しようとします。この関数の実行時間を考慮すると、最も簡単な方法は元のコードを変更することです:

import time
def f():
    start_time = time.time()
    print("hello")
    time.sleep(1)
    print("world")
    end_time = time.time()
    execution_time = (end_time - start_time)*1000
    print("time is %d ms" %execution_time)

ただし、実際の作業では、コア コードを直接変更できない場合があるため、元のコードを変更せずに, we 別の関数を定義できます (ただし、有効にするために関数を再度実行する必要があります)

import time
def deco(func):
    start_time = time.time()
    f()
    end_time = time.time()
    execution_time = (end_time - start_time)*1000
    print("time is %d ms" %execution_time)
def f():
    print("hello")
    time.sleep(1)
    print("world")
if __name__ == '__main__':
    deco(f)
    print("f.__name__ is",f.__name__)
    print()

ここでは、パラメータが関数である関数 deco を定義し、埋め込みます。タイミング関数を this function に追加します。しかし、これらの数千万の関数の関数を拡張したい場合、

は deco() 関数を 1000 万回実行することを意味するため、これは理想的ではありません。それを達成するためにデコレータを使用してみてください。まず、デコレータの最もオリジナルな外観を見てください。

import time
def deco(f):
    def wrapper():
        start_time = time.time()
        f()
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" %execution_time )
    return wrapper
@deco
def f():
    print("hello")
    time.sleep(1)
    print("world")
if __name__ == '__main__':
    f()

ここでの deco 関数は、最もオリジナルなデコレータです。そのパラメータは関数です。

関数 f() をパラメータとして、戻り関数 Wrapper() 内で実行され、関数 f() の前に @deco を追加します。 ##f() 関数は注入されるのと同じです タイミング関数を使用すると、f() が呼び出される限り、関数は「より多くの関数を備えた新しい関数」、

に変換されます (注入する必要はありません)元の関数を繰り返します).

拡張 1: 固定パラメーターを使用したデコレーター

import time
def deco(f):
    def wrapper(a,b):
        start_time = time.time()
        f(a,b)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
    return wrapper
@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f(3,4)

拡張 2: 固定パラメーターを使用しないデコレーター

import time
def deco(f):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time_ = (end_time - start_time)*1000
        print("time is %d ms" %execution_time)
    return wrapper
@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
@deco
def f2(a,b,c):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b+c))
if __name__ == '__main__':
    f2(3,4,5)
    f(3,4)

拡張 3: を使用します。関数を装飾するための複数のデコレータ

import time
def deco01(f):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
        print("deco01 end here")
    return wrapper
def deco02(f):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        f(*args, **kwargs)
        print("deco02 end here")
    return wrapper
@deco01
@deco02
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f(3,4)
'''
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here
'''

デコレータの呼び出し順序

デコレータは重ねて使用できるため、デコレータを使用した後のコードの順序はどうなりますか?

「 Python Sugar の @" 構文では、デコレーターが呼び出される順序は、@ 構文 Sugar を使用して宣言された順序の逆になります。

この例では、"f(3, 4) = deco01(deco02( f(3, 4)))"。

Python 組み込みデコレータ

Python には 3 つの組み込みデコレータがあります。クラスに関連するもの: staticmethod、classmethod、property 。

staticmethod はクラスの静的メソッドです。メンバー メソッドとの違いは、self パラメータがなく、クラスをインスタンス化せずに呼び出すことができることです。

クラスメソッドとメンバーメソッドの違いは、受け取った最初のパラメータがself(クラスインスタンスへのポインタ)ではなく、cls(現在のクラスの特定の型)であることです。

propertyはプロパティを意味し、次の情報を示します。クラス インスタンスを通じて直接アクセスできます

ここでは staticmethod と classmethod は紹介しませんので、例を通してプロパティを見てみましょう。

Pythonデコレータの詳しい解説Python の新しいスタイルのクラスの場合、上記の "@var.setter" デコレーターによって装飾されたメンバー関数が削除されると、Foo になることに注意してください。var 属性は読み取りです。 -only 属性であり、「foo.var = 'var 2'」を使用して値を割り当てると例外がスローされます。ただし、Python クラシック クラスの場合、宣言された属性は読み取り専用ではないため、「@var.setter」デコレータが削除されてもエラーは報告されません。

概要

この記事では、Python デコレーターの使用法をいくつか紹介します。デコレーターのコードは比較的理解しやすいものです。いくつかの例を通して実践すれば理解するのは簡単です。

以上がPythonデコレータの詳しい解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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