Python装飾器の簡単な理解

3660 ワード

装飾器の役割
 まず装飾器の役割を理解する:元の関数の機能を拡張する.アクセラレータを使用するメリットの1つは、元の関数コードを変更せずに新しい機能を提供できることであり、まず簡単な例を挙げて理解を深めることです. 私たちは今関数funcを持っています.主な仕事は「hello world」を印刷して1秒停止することです.
import time
def func():
   print("hello world")
   time.sleep(1)

 この場合、この関数の機能を拡張する場合は、例えば、この関数の消費時間を計算します.一般的には、元のコードに直接対応するコードを追加します.
import time
def func():
    start = time.time()
    print("hello world")
    time.sleep(1)
    end = time.time()
    print('cost time %s' % (end - start))

 この関数の灰常灰は常に重要だと仮定して、私はまた菜鶏coderで、またでたらめに変える勇気がなくて、どんな方法がありますか?ねえ、頭を働かせて、関数を書いて追加する機能を先に実現して、それから関数の中でfunc()を呼び出せばいいのではないでしょうか.次のようにします.
import time
def func():
    print("hello world")
    time.sleep(1)

def func2(func):
    start = time.time()
    func()
    end = time.time()
    print('cost time %s' % (end - start))

if __name__ == '__main__':
    func2(func)

 咳咳咳、本当に機知の小さい鬼ですね.しかし、私はすでに数十万行のコードを書いていて、中には数え切れないほどfunc関数を呼び出していると仮定します.今の新しいニーズは、時間をかけて印刷を計算する機能を追加することです.上記の方法では、func()を呼び出す場所を見つけ、コードをfunc 2()に変更するのに多くの時間を費やしますが、あなたは1ヶ月もこの仕事に費やしています.ボスは私が効率的ではないと言って、私を除名します......この時はどうすればいいですか?そこでまた頭がキラキラして、
import time
def decorator(func):
    def wrapper():
        start = time.time()
        func()
        end = time.time()
        print('decorator cost time %s' % (end - start))

    return wrapper

@decorator
def func():
    print("hello world")
    time.sleep(1)

if __name__ == '__main__':
    func()

これで私は1ヶ月かけてすべてのfunc()を修正する必要はありません.元のコードを維持し、新しい機能を追加しました.hhhは本当に天才です.関数にパラメータ(1つ、2つ、3つ、、、いくつか)を含める場合は、次のようにします.
import time
def decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print('decorator cost time %s' % (end - start))

    return wrapper

@decorator
def func(*args, **kwargs):
    print("hello world", args[0],args[1])
    time.sleep(1)

if __name__ == '__main__':
    func(1, 2)

ああ、そうだ、装飾器は複数あります.次のようにします.
import time
def decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print('decorator cost time %s' % (end - start))

    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print('decorator2 cost time %s' % (end - start))

    return wrapper

@decorator
@decorator2
def func(*args, **kwargs):
    print("hello world", args[0],args[1])
    time.sleep(1)

if __name__ == '__main__':
    func(1, 2)

 その起動順序は、関数に近いほど先に起動します.例えば、decorator 2を先に起動し、decoratorを起動します.はい、装飾器が何なのかを初歩的に把握することができます.簡単に運用することができます.
いくつかの装飾器の実際の役割を新しく更新します
まずコードを見てみましょう.
from functools import wraps
class OverrideException(Exception):
    """
           
    """

#         
def Const(cls):
    @wraps(cls)
    def new_setattr(self, name, value):
        raise OverrideException('const : {} can not be changed'.format(name))
    cls.__setattr__ = new_setattr
    return cls

@Const
class A(object):
    rich = 'rich'

a = A()
a.rich = 1
print(w.rich)

 「クラス変数の書き換えを防止する」機能をどのように実現するかを簡単に説明します.インスタンスaの変数に値を割り当てると、クラスメソッド___が呼び出されます.setattr____(*args,**kwargs)、上のコードではnew_setattr()メソッドで例外を放出し、__setattr____書き換えて、この時はアクセサリーで、あなたが守りたいクラスの属性を変更されないように保護することができます.注意Const(cls)のclsは私たちのクラスAで、注意して書いたのはクラスAの___です.setattr____.