装饰器

    • 一个函数对象是可调用对象。
    • 一个类对象是可调用对象,对它调用的结果就是返回类的实例
    • 实现了方法的类,其实例对象是可调用对象,对它调用的结果就是调用.__call__()方法

    装饰器有两种使用形式:

    • 函数的装饰器:在函数对象定义的时候使用装饰器,用于管理该函数对象
    • 类的装饰器:在类定义的时候使用该装饰器,用于管理该类以及类的实例

    2.函数的装饰器:用于管理函数。函数的装饰器声明为:

    即在正常的函数定义之前冠以说明符(即装饰器声明)。它等价于:

    1. def func(*pargs,**kwargs):
    2. pass
    3. func=decorator(func)
    • 类中的@staticmethod@property均为装饰器
    • 执行了装饰器的def之后,函数名指向的不再是原来的函数对象,而是:

      • 一个可调用对象, 当decorator是个函数时由decorator(func)函数返回的
      • decorator类的实例,当decorator是个类时,由decorator(func)构造方法返回

      函数的装饰器

    3.类的装饰器:用于管理类。类的装饰器声明为:

    1. @decorator
    2. class A:
    3. pass
    1. class A:
    2. pass
    3. A=decorator(A)
    • 类的装饰器并不是拦截创建实例的函数调用,而是返回一个不同的可调用对象
    • 执行了装饰器的class之后,类名指向的不再是原来的类对象,而是:

      • 一个可调用对象, 当decorator是个函数时由decorator(func)函数返回的
      • decorator类的实例,当decorator是个类时,由decorator(func)构造方法返回

    3.装饰器只是一个返回可调用对象的可调用对象,它没有什么特殊的地方。

    • 可以用函数实现装饰器:
    1. def decorator(func): #定义了一个叫decorator的装饰器
    2. #某些处理
    3. return func #返回可调用对象
    • 也可以用类来实现装饰器:
    • 通常用嵌套类来实现装饰器:
    1. def decorator(func): #定义了一个叫decorator的装饰器
    2. def wrapper(*args):
    3. #使用func或其他的一些工作
    4. return wrapper #返回可调用对象

    三种装饰器的实现

    4.装饰器的嵌套:

    • 函数的装饰器的嵌套:
    1. @decoratorA
    2. def func():
    3. pass

    等价于

    1. def f():
    2. pass
    3. f=A(B(C(f)))
    • 类的装饰器的嵌套:
    1. @decoratorA
    2. @decoratorB
    3. @decoratorC
    4. class M:
    5. pass

    等价于

    每个装饰器处理前一个装饰器返回的结果,并返回一个可调用对象

    5.装饰器可以携带参数。

    • 函数定义的装饰器带参数:它其实是一个嵌套函数。
      • 外层函数的参数为装饰器参数,返回一个函数(内层函数)
      • 内层函数的参数为func,返回一个可调用参数,内层函数才是真正的装饰器
    1. def decorator(*args,**kwargs):
    2. print("this is decorator1:",args,kwargs)
    3. def actualDecorator(func): # 这才是真实的装饰器
    4. ...
    5. return func
    6. return actualDecorator
    • 类定义的装饰器带参数:它其实是一个嵌套类。
      • 外层类的初始化函数的参数为装饰器参数,外层类的__call__函数的参数为func,返回值为一个类的实例(内部类实例)
      • 内层类的初始化函数参数为func;内层类的__call__函数使用func内层类才是真正的装饰器
    1. class decorator2:
    2. class ActualDecorator: #这才是真实的装饰器
    3. def __init__(self,func):
    4. ...
    5. self.func=func#记住func
    6. def __call__(self,*args,**kwargs):
    7. ...
    8. return self.func(*args,**kwargs) #使用func
    9. def __init__(self,*args,**kwargs):
    10. ...
    11. ...
    12. return decorator2.ActualDecorator(func)

    总结:

    • 不带参数的装饰器decorator装饰一个名字(可能为函数名、也可能为类名):则执行的是:F=decorator(F),直接使用F
    • 带参数的装饰器decorator装饰一个名字F(可能为函数名、也可能为类名)@decorator(args):则执行的是:F=decorator(args)(F),间接使用F

    6.利用装饰器可以实现单例模式:

    1. def Singleton(cls):
    2. instance=None
    3. def onCall(*args,**kwargs):
    4. nonlocal instance
    5. if instance == None:
    6. instance=cls(*args,**kwargs)
    7. return instance
    8. return onCall
    9. @Singleton
    10. class A:
    11. pass

    利用装饰器实现单例模式

    7.利用装饰器可以跟踪对象的调用接口,从而管理对实例的接口访问(如统计调用次数,打印调用日志)

    1. def Tracer(cls):
    2. class Wrapper:
    3. def __init__(self,*args,**kwargs):
    4. self.wrapped=cls(*args,**kwargs)
    5. def __getattr__(self,name):
    6. print('Trace:'+name)
    7. return getattr(self.wrapped,name)
    8. return Wrapper
    9. @Tracer
    10. class A:
    11. pass

    8.装饰器也可以直接管理函数和类,而不仅仅只是管理对他们的调用

    • 利用装饰器添加函数和类到注册表:

    利用装饰器添加函数到注册表

    • 利用装饰器为函数和类添加属性
    1. def register(obj):
    2. obj.label=0
    3. return obj
    4. @register
    5. def func():
    6. pass