网络编程
位置:首页>> 网络编程>> Python编程>> Python Decorator装饰器的创建方法及常用场景分析

Python Decorator装饰器的创建方法及常用场景分析

作者:什么都干的派森  发布时间:2022-05-05 03:34:11 

标签:Python,Decorator,装饰器

前言

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

来源:https://blog.csdn.net/weixin_43721000/article/details/125590006

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com