Python Decorator装饰器
什么都干的派森 人气:0前言
1.装饰器本质是一个语法糖,是对被装饰方法或类进行的功能扩充,是一种面向切面的实现方法
2.装饰器可以分成方法装饰器和类装饰器,他们的区别是一个是用函数实现的装饰器,一个是用类实现的装饰器,他们也都能在方法和类上进行装饰
3.类装饰器看起来结构更加清晰,因此下面的代码实现的装饰器全是类装饰器
一、创建方式
1.创建“装饰方法”的类装饰器
from functools import wraps # 装饰器类 class MyDecorator(object): def __init__(self, plusNum): self.plusNum = plusNum # 装饰器入参 def __call__(self, func): @wraps(func) # @wraps保证装饰器不改变被装饰方法的原有函数结构 def wrapped_function(*args, **kwargs): # 调用被装饰方法前执行一些操作 --------------- # 如果不加@wraps,此处打印结果将是 funcName = func.__name__ print("funcName: {}".format(funcName)) # --------------------------------------- # 修改被装饰方法的入参 -- num1 = args[0] + 2 num2 = args[1] + 3 args = (num1, num2) # ------------------- # 执行被装饰方法 ------------- res = func(*args, **kwargs) # ------------------------- # 调用被装饰方法后执行一些操作 ------------- print("do something after the func...") # ------------------------------------- # 修改被装饰方法的出参 -- res += self.plusNum # ------------------- # 返回被装饰方法的参数 return res # 返回装饰器方法 return wrapped_function # 被装饰的方法 @MyDecorator(3) def add(num1, num2): return num1+num2 if __name__ == '__main__': # 整体执行流程: # 1. 打印 add 方法名 # 2. 修改被装饰方法入参 # 3. 执行被装饰方法 # 4. 调用被装饰方法后执行一些操作 # 5. 修改被装饰方法的出参 # 6. 打印结果 print(add(5, 3)) # funcName: add # do something after the func... # 16
2.创建“装饰类中方法”的类装饰器
from functools import wraps # 装饰器类 class MyDecorator(object): def __init__(self, plusNum): self.plusNum = plusNum # 装饰器入参 def __call__(self, func): @wraps(func) # @wraps保证装饰器不改变被装饰方法的原有函数结构 def wrapped_function(*args, **kwargs): # 此处与直接装饰方法相同 # 调用被装饰方法前执行一些操作 --------------- # 如果不加@wraps,此处打印结果将是 funcName = func.__name__ print("funcName: {}".format(funcName)) # --------------------------------------- # 此处需要注意,如果需要修改入参的值,那么传参的索引是从1开始而不是从0开始,因为第一个入参的值是实例本身self # 修改被装饰方法的入参 -- num1 = args[1] + 2 num2 = args[2] + 3 args = (args[0], num1, num2) # ------------------- # 此处与直接装饰方法相同 # 执行被装饰方法 ------------- res = func(*args, **kwargs) # ------------------------- # 此处与直接装饰方法相同 # 调用被装饰方法后执行一些操作 ------------- print("do something after the func...") # ------------------------------------- # 此处与直接装饰方法相同 # 修改被装饰方法的出参 -- res += self.plusNum # ------------------- # 返回被装饰方法的参数 return res # 返回装饰器方法 return wrapped_function class Operation(object): # 被装饰的类方法 @MyDecorator(3) def add(self, num1, num2): return num1+num2 if __name__ == '__main__': op = Operation() print(op.add(3, 5)) # funcName: add # do something after the func... # 16
3.创建“装饰类”的类装饰器
from functools import wraps # 装饰器类 class MyDecorator(object): def __init__(self, plusNum): self.plusNum = plusNum # 装饰器入参 def __call__(self, Cls): @wraps(Cls) # @wraps保证装饰器不改变被装饰类的原有结构 def wrapped_function(*args, **kwargs): # 调用被装饰类前执行一些操作 --------------- # 如果不加@wraps,此处打印结果将是 clsName = Cls.__name__ print("clsName: {}".format(clsName)) # --------------------------------------- # 修改被装饰类的入参 --- num1 = args[0] + 2 num2 = args[1] + 3 args = (num1, num2) # ------------------- # 初始化被装饰类 ------------- cls = Cls(*args, **kwargs) # ------------------------- # 初始化后执行一些操作 -------------------- print("do something after the func...") # ------------------------------------- # 给类实例增加增加属性和方法 --------------------- cls.mul = 3 # 增加属性 cls.plusNumber = self.plusNumber # 增加方法 # ------------------------------------------- # 返回实例 return cls # 返回装饰器方法 return wrapped_function def plusNumber(self, num): return num + self.plusNum # 被装饰的类 @MyDecorator(3) class Operation(object): def __init__(self, num1, num2): self.num1 = num1 self.num2 = num2 def add(self): num3 = self.num1 + self.num2 num4 = self.plusNumber(num3*self.mul) # 使用装饰器插入的属性和方法 return num4 if __name__ == '__main__': # 整体执行流程: # 1. 打印 Operation 类名 # 2. 修改类的初始化参数 # 3. 初始化类 # 4. 初始化完成后执行一些方法 # 5. 给初始化的实例新增 mul 属性和 plusNumber 方法 # 6. 实例执行 add 函数并调用新增的装饰函数和装饰属性 # 7. 输出结果 op = Operation(3, 5) print(op.add()) # clsName: Operation # do something after the func... # 42
二、常用场景
1.记录日志
# todo
2.性能测试
# todo
3.循环执行
# todo
4.拦截器
# todo
5.数据预处理(数据清洗)
# todo
6.功能植入
# todo
加载全部内容