Python Decorator装饰器的创建方法及常用场景分析
作者:什么都干的派森 时间:2022-05-05 03:34:11
前言
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
标签:Python,Decorator,装饰器
0
投稿
猜你喜欢
Python程序设计入门(2)变量类型简介
2021-09-28 14:51:18
Python快速实现一个线程池的示例代码
2021-06-01 04:51:01
js实现随屏幕滚动的带缓冲效果的右下角广告代码
2024-06-07 15:26:48
如何通过pycharm实现对数据库的查询等操作(非多步操作)
2024-01-25 03:31:37
SQL中JOIN和UNION区别、用法及示例介绍
2012-08-21 10:47:22
mysql缓冲和缓存设置详解
2024-01-27 02:39:18
JavaScript函数封装的示例详解
2024-04-25 13:15:51
java使用正则表达式查找包含的字符串示例
2022-06-18 21:02:08
python3库numpy数组属性的查看方法
2023-07-19 07:25:50
python3实现磁盘空间监控
2023-07-09 14:12:49
举例讲解Python设计模式编程的代理模式与抽象工厂模式
2021-08-13 06:23:49
Python __setattr__、 __getattr__、 __delattr__、__call__用法示例
2022-06-11 20:19:22
用pandas中的DataFrame时选取行或列的方法
2023-05-15 07:43:04
利用 Python 实现多任务进程
2023-12-19 02:53:52
非常不错的[JS]Cookie精通之路第1/2页
2023-09-04 04:04:34
python队列通信:rabbitMQ的使用(实例讲解)
2021-01-11 05:04:55
python__name__原理及用法详解
2021-04-07 02:47:51
pandas中.loc和.iloc以及.at和.iat的区别说明
2022-04-28 01:17:47
js同时按下两个方向键
2024-05-02 17:21:45
MySQL索引优化实例分析
2024-01-26 18:34:27