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
投稿
猜你喜欢
- 好了,看看我们的代码吧:upload.htm' 上传页面<html> <body>&nb
- Array.prototype._ = function(){var _p = 0;var _v = 0;(function(){ 
- 虽然ting88没有注册的用户不能下载歌曲,但搞定它也非难事啊:)进入www.ting88.com的网站,把歌手专辑页面的URL复制到文本框
- 支持实时监控sliderbar的数据,允许有callback回调的函数,有示例1、可自定样式SetStyle() 2、带有onSroll功能
- 把程序重新写了一遍,日期下拉选择器,可自定义日期范围。使用了一个技巧获取指定月份的天数。演示页面:DateSelector.htm 程序代码
- 本文实例讲述了Python 私有化操作。分享给大家供大家参考,具体如下:私有化xx: 公有变量_x: 单前置下划线,私有化属性或方法,fro
- 运行截图运行效果:什么?你说你看不清烟花?那我换一种颜色,请点开看。实现过程准备工作使用语言和框架:python、pygame。安装pyga
- 这篇文章主要介绍了python线程信号量semaphore使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价
- 回车和换行的历史:机械打字机有回车和换行两个键作用分别是:换行就是把滚筒卷一格,不改变水平位置。 (即移到下一行,但不是行首,而是和上一行水
- 前言问题:我们在放大图片的过程中,放大的目标图像和原图图像之间会存在不同。放大的基本思想:第一步:将目标图像进行缩小到原图像的尺寸,虚拟的将
- python pycharm中使用opencv时,没有代码自动补全提示解决方案有2种今天工作时突然发现,在写OPENCV相关代码时,没有自动
- 父层: <div class="col-xs-12"> <div class
- 一个用asp来处理jmail发信的过程,及使用方法. 发信时,直接调用这个过程就行了,很方便。<% dim
- 由于内容过多,大家可以通过ctrl+F搜索即可IE浏览器id 后缀名 php识别出的文件类型0 gif image/gif1 jpg ima
- 1、遇到的问题:numpy版本im_data = dataset.ReadAsArray(0,0,im_width,im_height)#获
- 最近 全栈数据工程师养成攻略 的微信群已经将近500人,开了二群之后为了打通不同微信群之间的消息,花了点时间做了个消息同步机器人,在任意群收
- 内容简介展示如何给图像叠加不同等级的椒盐噪声和高斯噪声的代码,相应的叠加噪声的已编为对应的类,可实例化使用。以下主要展示自己编写的:加噪声的
- 如何用ASP输出HTML文件?<!--#include file="top.inc"--><
- PyMysql使用详解在编写小脚本时,PyMysql是快速连接并操作数据库的一个不错选择。安装pip3 install PyMysql# 可
- 什么是网络?网络是由节点和连线构成,表示诸多对象及其相互联系。在数学上,网络是一种图,一般认为专指加权图。网络除了数学定义外,还有具体的物理