[python入门㊻] - python装饰器和类的装饰器
目录
❤ python装饰器介绍
❤ 什么是装饰器
❤ 装饰器的流程
❤ 定义装饰器时通常会涉及以下3个函数
无参装饰器
有参装饰器
多重装饰器
❤ 装饰器的用法(闭包)
❤ 装饰器语法糖
❤ 时间计时器
❤ 装饰器中@wraps作用
不使用@wraps装饰器
使用@wraps装饰器解决这个问题
❤ 装饰器顺序
❤ 类的装饰器 - classmethod
绑定到对象的方法
绑定到类的方法
❤ 类的装饰器 - property
❤ 类的装饰器 - staticmethod
❤ python装饰器介绍
- 在Python中,装饰器(decorator)是在闭包的基础上发展起来的。
- 装饰器的实质是一个高阶函数,其参数是要装饰的函数名,其返回值是完成装饰的函数名,其作用是为已经存在的函数对象添加额外的功能,其特点是不需要对原有函数做任何代码上的变动。
- 装饰器在本质上也是一个嵌套函数,其外层函数的返回值是一个新的函数对象引用,所不同的是,其外层函数可以接受一个现有函数对象引用作为参数。
- 装饰器可以用于包装现有函数,即在不修改任何代码的前提下为现有函数增加额外功能。
- 装饰器通常应用于有切面(面向切面编程是指运行时动态实现程序维护的一种技术)需求的场景,例如插入日志、性能测试、事务处理、缓存以及权限校验等。
- 装饰器是解决这类问题的绝佳设计,有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用它们。
❤ 什么是装饰器
装饰是为函数和类指定管理代码的一种方式。Python装饰器以两种形式呈现:
- 函数装饰器在函数定义的时候进行名称重绑定。提供一个逻辑层来管理函数和方法或随后对它们的调用。
- 类装饰器在类定义的时候进行名称重绑定,提供一个逻辑层来管理类。或管理随后调用它们所创建的实例。
❤ 装饰器的流程
- A函数是装饰器,B函数是A函数传入的参数。
-
将B函数在A函数中执行,在A函数中可以选择执行或不执行,也可以对B函数的结果进行二次加工处理。
简而言之,装饰器提供了一种方法,在函数和类定义语句的末尾插入自己主动执行的代码——对于函数装饰器。在def的末尾。对于类装饰器,在class的末尾。
这种代码能够扮演不同的角色。
装饰器提供了一些和代码维护性和审美相关的有点。此外,作为结构化工具,装饰器自然地促进了代码封装,这降低了冗余性并使得未来变得更easy。
❤ 定义装饰器时通常会涉及以下3个函数:
1)装饰器函数:它在函数嵌套关系中作为外层函数出现,其函数体内容包括定义一个内层函数以完成装饰功能的函数,通过return语句向调用者返回内层函数对象引用。
2)目标函数:即需要进行装饰的函数,它作为装饰器函数的形参出现,该函数的定义则出现在调用装饰器的地方。
3)完成装饰的函数:它在函数嵌套关系中作为内层函数出现,用于为待装饰的目标函数添加额外功能。在这个内层函数中要调用目标函数,并为目标函数添加一些新的功能
无参装饰器
def 装饰器名称(待装饰器函数名称):def 装饰器函数名称():# 目标函数执行前 添加额外功能# 目标函数调用 待装饰器函数执行# 目标函数执行后 添加额外功能return 装饰器函数名称def decorator(func):def inner(*args, **kwargs):# func是被装饰的对象,这里可以写执行前的功能res = func(*args, **kwargs)# func是被装饰的对象,这里可以写执行后的功能return inner# 使用装饰器@装饰器名称
def 需装饰函数名称():pass
无参数装饰器本质就是一个双层结构的高阶函数,有参数装饰器则是一个3层结构的高阶函数。
有参装饰器
def 装饰器名称(参数1, 参数2,...):def 中间层装饰器函数名称(待装饰器函数名称)def 里层装饰器函数名称():# 目标函数执行前 添加额外功能# 目标函数调用 待装饰器函数执行# 目标函数执行后 添加额外功能return 装饰器函数名称return 中间层装饰器函数名称def decorator(arg1, arg2):def middle(func):def inner(*args, **kwargs):# func是被装饰的对象,这里可以写执行前的功能 可使用参数 arg1, arg2res = func(*args, **kwargs)# func是被装饰的对象,这里可以写执行后的功能 可使用参数 arg1, arg2return innerreturn middle# 使用装饰器@装饰器名称(arg1, arg2)
def 需装饰函数名称():pass
多重装饰器
多重装饰器是指使用多个装饰器来修改同一个函数。此时要注意多重装饰器的执行顺序是后面的装饰器先执行,前面的装饰器后执行,即后来者居上
def first(func):def inner(*args, **kwargs):print("函数:first执行...")func(*args, **kwargs)print("函数:first完成")return innerdef second(func):def inner(*args, **kwargs):print("函数:second执行...")func(*args, **kwargs)print("函数:second完成")return inner# 两装饰器应用于同一函数@first
@second
def test():print("函数:test执行")# 执行结果
"""
函数:first执行...
函数:second执行...
函数:test执行
函数:second完成
函数:first完成
"""
❤ 装饰器的用法(闭包)
闭包(Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。
这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。
def print_msg(): # print_msg是外围函数msg = "I'm closure"def printer(): # printer是嵌套函数print(msg)return printerclosure = print_msg() # 这里获得的就是一个闭包
closure() # 输出 I'm closure
msg是一个局部变量,在print_msg函数执行之后就不会存在了。
但是嵌套函数引用了这个变量,将这个局部变量封闭在了嵌套函数中,这样就形成了一个闭包。
❤ 装饰器语法糖
语法糖(Syntactic sugar),也译为糖衣语法,指计算机语言中添加的某种语法。
这种语法对语言的功能并没有影响,但是更方便程序员使用。
通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。
@ 符号是装饰器的语法糖。它放在一个函数开始定义的地方(头顶),和这个函数绑定在一起。
在我们调用这个函数的时候,会先将这个函数做为参数传入它头顶,即装饰器里。
❤ 时间计时器
以下用装饰器来实现计算一个函数的执行时长,让函数睡眠3秒
# 这是装饰函数
def timer(func):def wrapper(*args, **kw):start_time = time.time()func(*args, **kw) # 这是函数真正执行的地方stop_time = time.time()cost_time = stop_time - start_timeprint("花费时间:{}秒".format(cost_time))return wrapperimport time@timer
def want_sleep(sleep_time):time.sleep(sleep_time)want_sleep(3)
❤ 装饰器中@wraps作用
装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变)。
为了不影响,Python的functools包中提供了一个叫wraps的装饰器来消除这样的副作用。
写一个装饰器的时候,最好在实现之前加上functools中的wraps,它能保留原有函数的名称和文档字符串(DocStrings)。
文档字符串用于解释文档程序,帮助程序文档更加简单易懂。
可以在函数体的第一行使用一对三个单引号 ‘’’ 或者一对三个双引号 “”" 来定义文档字符串。
使用 doc(注意双下划线)调用函数中的文档字符串属性。
不使用@wraps装饰器
def decorator(func):"""this is decorator __doc__"""def wrapper(*args, **kwargs):"""this is wrapper __doc__"""print("this is wrapper method")return func(*args, **kwargs)return wrapper@decorator
def test():"""this is test __doc__"""print("this is test method")print("__name__: ", test.__name__)
print("__doc__: ", test.__doc__)
输出:
__name__: wrapper
__doc__: this is wrapper __doc__
分析:
对test()方法进行装饰时候,实际上是
test = decorator(test)
返回的是wrapper方法的引用,也就是让test指向了wrapper方法,所以调用test.name, 实际上是wrapper.name。
这造成后面查找该方法的名字和注释时得到装饰器内嵌函数的名字和注释。
使用@wraps装饰器解决这个问题
from functools import wrapsdef decorator(func):"""this is decorator __doc__"""@wraps(func)def wrapper(*args, **kwargs):"""this is wrapper __doc__"""print("this is wrapper method")return func(*args, **kwargs)return wrapper@decorator
def test():"""this is test __doc__"""print("this is test method")print("__name__: ", test.__name__)
print("__doc__: ", test.__doc__)
输出:
__name__: test
__doc__: this is test __doc__
❤ 装饰器顺序
一个函数可以同时定义多个装饰器,比如:
@a
@b
@c
def f ():pass
它的执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,它等效于:
f = a(b(c(f)))
❤ 类的装饰器 - classmethod
@classmethod: *****
类的对象绑定的方法都是默认传self参数的,但是当这个self在方法中不被使用时,
然后在方法中准备使用类的静态属性,就可以将该方法修改为类方法
在外部可以不用实例化对象直接通过类名调用类方法
绑定到对象的方法:
在类内部没有任何修饰的情况下直接定义一个方法默认绑定一个self给对象来用
class Mysql:def __init__(self,host,port):self.host=hostself.port=portdef tell_info(self): print("<%s:%s>" %(self.host,self.port))conn1=Mysql('127.0.0.1',8080)
conn1.tell_info()
输出:
<127.0.0.1:8080>
绑定到类的方法:
当函数体代码需要传进来的参数不再是对象了,而是类的时候
以下是实现从配置文件里读IP和端口,完成实例化的程序:
settings
import settingsclass Mysql:def __init__(self,host,port):self.host=hostself.port=portdef tell_info(self):print("<%s:%s>" %(self.host,self.port))@classmethod #绑定给类,由类来掉,把它当做第一个参数传进来完成实例化,再把结果返回def from_conf(cls):return cls(settings.HOST, settings.PORT)conn2=Mysql.from_conf()print(conn2.tell_info)
conn2.tell_info()# 打印结果:<bound method Mysql.tell_info of <__main__.Mysql object at 0x00C9CFF0>> <1.1.1.1:8080>
我们得出以下结论:
- 在带有 classmethod 装饰器 的 函数 内,是无法调用普通的 带有 self 的函数的
- 但是在普通的带有 self 的类函数内,是可以调用带有 classmethod 装饰器 的 函数的
❤ 类的装饰器 - property
property是一种特殊的属性,可实现把函数名变为属性名使用。它可以在不改变类接口的前提下使用存取方法 (即读值和取值)
来修改数据的属性,property类有3个方法getter(读操作)、setter(赋值操作)、deleter(删除操作),分别把对应的操作
绑定到指定的函数实现,应用如下:
class People:def __init__(self,name,weight,height):self.name=nameself.wt=weightself.ht=height@propertydef bmi(self):return self.wt / (self.ht ** 2)@property #便于用户访问隐藏的内部值namedef name(self):return self.__name@name.setter #便于用户 修改name值def name(self,obj): #obj='EGON'if not isinstance(obj,str):raise TypeError('名字的值必须是str类型')self.__name=obj #self.__name='EGON'@name.deleterdef name(self):del self.__namep=People('egon',75,1.80)
# print(p.bmi)# print(p.name)
# p.name='EGON'
# p.name=123 #报错
# print(p.name)# del p.name #删除name
❤ 类的装饰器 - staticmethod
非绑定方法,不与任何东西绑定,定义的函数不需要任何东西传进来
import uuidclass Mysql:def __init__(self,host,port):self.host=hostself.port=port@staticmethoddef create_id():return uuid.uuid4()print(Mysql.create_id)
print(Mysql.create_id())#打印结果:<function Mysql.create_id at 0x02C6EC90> 2209806a-5ffc-47f2-86f1-cb2ac64ce404
整体代码:
import settings
import uuidclass Mysql:def __init__(self,host,port):self.host=hostself.port=portdef tell_info(self):print("<%s:%s>" %(self.host,self.port))@classmethoddef from_conf(cls):return cls(settings.HOST, settings.PORT)@staticmethoddef create_id():return uuid.uuid4()conn1=Mysql('127.0.0.1',8080)
conn1.tell_info()conn2=Mysql.from_conf()
conn2.tell_info()
print(conn2.tell_info)print(Mysql.create_id)
print(Mysql.create_id())#打印结果:<127.0.0.1:8080> <1.1.1.1:8080> <bound method Mysql.tell_info of <__main__.Mysql object at 0x038294B0>> <function Mysql.create_id at 0x03831E40> bab5e25e-7de3-4273-a8cf-40829c716d87
附:使用最广泛的装饰器为 classmethod
相关文章:
[python入门㊻] - python装饰器和类的装饰器
目录 ❤ python装饰器介绍 ❤ 什么是装饰器 ❤ 装饰器的流程 ❤ 定义装饰器时通常会涉及以下3个函数 无参装饰器 有参装饰器 多重装饰器 ❤ 装饰器的用法(闭包) ❤ 装饰器语法糖 ❤ 时间计时器 ❤ 装饰器中wraps作用 不使用wraps装饰器 使用wraps装饰器解…...
企业级信息系统开发学习1.1 初识Spring——采用Spring配置文件管理Bean
文章目录一、Spring容器演示——采用Spring配置文件管理Bean(一)创建Maven项目(二)添加Spring依赖(三)创建杀龙任务类(四)创建勇敢骑士类(五)采用传统方式让勇…...
CSS盒子模型
盒子模型 CSS三大特性 继承性、层叠性、优先级 优先级比较 继承 < 通配符选择器 < 标签选择器 < 类选择器 < id选择器 < 行内样式 < !important 注意:!important不能提升继承的优先级,只要是继承优先级最低 复合选择器权重叠加计…...
Python基础学习笔记 —— 数据结构与算法
数据结构与算法1 数据结构基础1.1 数组1.2 链表1.3 队列1.4 栈1.5 二叉树2 排序算法2.1 冒泡排序2.2 快速排序2.3 (简单)选择排序2.4 堆排序2.5 (直接)插入排序3 查找3.1 二分查找1 数据结构基础 本章所需相关基础知识:…...
笔记本连接wifi,浏览器访问页面,显示访问被拒绝
打开chrome、edge浏览器访问第1个第2个页面正常,后面再打开页面显示异常。 但手机连接正常,笔记本连接异常,起初完全没有怀疑是wifi问题 以为用了vpn软件问题,认为中了病毒。杀毒,并没有中毒。 1、关闭vpn代理&#…...
36个物联网专业毕业论文选题推荐
物联网技术在智能家居系统中的应用研究物联网在智慧城市建设中的作用物联网在工业4.0中的实现与发展 物联网与智能物流系统的结合物联网与医疗健康领域的融合研究物联网与环境监测系统的集成物联网与农业生产的结合研究物联网技术对汽车行业的影响与发展物联网在智能安防领域的…...
Pytorch复习笔记--torch.nn.functional.interpolate()和cv2.resize()的使用与比较
1--前言 博主在处理图片尺度问题时,习惯使用 cv2.resize() 函数;但当图片数据需用显卡加速运算时,数据需要在 GPU 和 CPU 之间不断迁移,导致程序运行效率降低; Pytorch 提供了一个类似于 cv2.resize() 的采样函数&…...
ASP.NET Core MVC 项目 AOP之ActionFilterAttribute
目录 一:说明 二:实现ActionFilterAttribute父类 一:说明 ActionFilterAttribute比前两者简单方便,易于扩展,不易产生代码冗余。 ActionFilterAttribute过滤器执行顺序: 1:执行控制器中的构造函数,实例化控制器 2:执行ActionFilterAttribute.OnActionExecutionA…...
浅析EasyCVR安防视频能力在智慧小区建设场景中的应用及意义
一、行业需求 城市的发展创造了大量工作机会,人口的聚集也推动了居民住宅建设率的增长。人民生活旨在安居乐业,能否住得“踏实”是很多劳动工作者最关心的问题。但目前随着住宅小区规模的不断扩大、人口逐渐密集,在保证居住环境舒适整洁的同…...
Python的深、浅拷贝到底是怎么回事?一篇解决问题
嗨害大家好鸭!我是小熊猫~ 一、赋值 Python中, 对象的赋值都是进行对象引用(内存地址)传递, 赋值(), 就是创建了对象的一个新的引用, 修改其中任意一个变量都会影响到另一个 will …...
TCP协议十大特性
日升时奋斗,日落时自省 目录 1、确认应答 1.1、序号编辑 2、超时重传 3、连接管理 3.1、三次握手 3.2、四次挥手 4、滑动窗口 5、流量控制 6、拥塞控制 7、延时应答 8、捎带应答 9、面向字节流 10、异常情况 TCP协议: 特点:有…...
2.14作业【GPIIO控制LED】
设备树 myleds{ myled1 <&gpioe 10 0>; myled2 <&gpiof 10 0>; myled3 <&gpioe 8 0>; }; 驱动代码 #include<linux/init.h> #include<linux/module.h> #include<linux/of.h&…...
5min搞定linux环境Jenkins的安装
5min搞定linux环境Jenkins的安装 安装Jenkinsstep1: 使用wget 命令下载Jenkinsstep2、创建Jenkins日志目录并运行jekinsstep3、访问jenkins并解锁jenkins,安装插件以及创建管理员用户step4、到此,就完成了Finish、以上步骤中遇到的问题1、 jenkins启动不了2、jenkins无法访问…...
Cortex-M0存储器系统
目录1.概述2.存储器映射3.程序存储器、Boot Loader和存储器重映射4.数据存储器5.支持小端和大端数据类型数据对齐访问非法地址多寄存器加载和存储指令的使用6.存储器属性1.概述 Cortex-M0处理器具有32位系统总线接口,以及32位地址线(4GB的地址空间&…...
软件测试——测试用例之场景法
一、场景法的应用场合 场景法主要用于测试软件的业务流程和业务逻辑。场景法是基于软件业务的测试方法。在场景法中测试人员把自己当成最终用户,尽可能真实的模拟用户在使用此软件的操作情景: 重点模拟两类操作: 1)模拟用户正确…...
英文写作中的常用的衔接词
1. 增补 (Addition) in addition, furthermore, again, also, besides, moreover, whats more, similarly, next, finally 2.比较(Comparision) in the same way, similarly, equally, in comparison, just as 3. 对照 (Contrast) in contrast, on …...
新库上线 | CnOpenData中国地方政府债券信息数据
中国地方政府债券信息数据 一、数据简介 地方政府债券 指某一国家中有财政收入的地方政府地方公共机构发行的债券。地方政府债券一般用于交通、通讯、住宅、教育、医院和污水处理系统等地方性公共设施的建设。地方政府债券一般也是以当地政府的税收能力作为还本付息的担保。地…...
Python 条件语句
Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块。 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何非0和非空(null)值为true,0 或者 null为false。 Python 编…...
C语言思维导图大总结 可用于期末考试 C语言期末考试题库
目录 一.C语言思维导图 二.C语言期末考试题库 一.C语言思维导图 导出的图可能有点糊,或者查看链接:https://share.weiyun.com/uhf1y2mp 其实原图是彩色的不知道为什么导出时颜色就没了 部分原图: 也可私信我要全图哦。 图里的链接可能点不…...
从零实现深度学习框架——再探多层双向RNN的实现
来源:投稿 作者:175 编辑:学姐 往期内容: 从零实现深度学习框架1:RNN从理论到实战(理论篇) 从零实现深度学习框架2:RNN从理论到实战(实战篇) 从零实现深度…...
Flink 连接流详解
连接流 1 Union 最简单的合流操作,就是直接将多条流合在一起,叫作流的“联合”(union)。联合操作要求必须流中的数据类型必须相同,合并之后的新流会包括所有流中的元素,数据类型不变。这种合流方式非常简…...
分享112个HTML电子商务模板,总有一款适合您
分享112个HTML电子商务模板,总有一款适合您 112个HTML电子商务模板下载链接:https://pan.baidu.com/s/13wf9C9NtaJz67ZqwQyo74w?pwdzt4a 提取码:zt4a Python采集代码下载链接:采集代码.zip - 蓝奏云 有机蔬菜水果食品商城网…...
2023备战金三银四,Python自动化软件测试面试宝典合集(八)
马上就又到了程序员们躁动不安,蠢蠢欲动的季节~这不,金三银四已然到了家门口,元宵节一过后台就有不少人问我:现在外边大厂面试都问啥想去大厂又怕面试挂面试应该怎么准备测试开发前景如何面试,一个程序员成长之路永恒绕…...
J-Link RTT Viewer使用教程(附代码)
目录 RTT(Real Time Transfer)简介 使用教程 常用API介绍 RTT缓冲大小修改 使用printf重定向 官方例程 RTT(Real Time Transfer)简介 平常调试代码中使用串口打印log,往往需要接出串口引脚,比较麻烦,并且串口打印速度较慢,串…...
C语言——指针、数组的经典笔试题目
文章目录前言1.一维数组2.字符数组3.二维数组4.经典指针试题前言 1、数组名通常表示首元素地址,sizeof(数组名)和&数组名两种情况下,数组名表示整个数组。 2、地址在内存中唯一标识一块空间,大小是4/8字节。32位平台4字节,64位…...
【C语言】程序环境和预处理|预处理详解|定义宏(上)
主页:114514的代码大冒险 qq:2188956112(欢迎小伙伴呀hi✿(。◕ᴗ◕。)✿ ) Gitee:庄嘉豪 (zhuang-jiahaoxxx) - Gitee.com 文章目录 目录 文章目录 前言 一、程序的翻译环境和执行环境 二、详解编译和链接 1.翻译环境 2.编…...
上海霄腾自动化装备盛装亮相2023生物发酵展
上海霄腾自动化携液体膏体粉剂颗粒等灌装生产线解决方案亮相2023生物发酵展BIO CHINA2023生物发酵展,作为生物发酵产业一年一度行业盛会,由中国生物发酵产业协会主办,上海信世展览服务有限公司承办,2023第10届国际生物发酵产品与技…...
python+flask开发mock服务
目录 什么是mock? 什么时候需要用到mock? 如何实现? pythonflask自定义mock服务的步骤 一、环境搭建 1、安装flask插件 2、验证插件 二、mock案例 1、模拟 返回结果 2、模拟 异常响应状态码 3、模拟登录,从jmeter中获取…...
数据库(三)
第三章 MySQL库表操作 3.1 SQL语句基础 3.1.1 SQL简介 SQL:结构化查询语言(Structured Query Language),在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。使用SQL语句,程序员和数据库管理员可以完成如下的任务。 改变数据…...
2023软考纸质证书领取通知来了!
不少同学都在关注2022下半年软考证书领取时间,截止至目前,上海、湖北、江苏、南京、安徽、山东、浙江、宁波、江西、贵州、云南、辽宁、大连、吉林、广西地区的纸质证书可以领取了。将持续更新2022下半年软考纸质证书领取时间,请同学们在证书…...
北京网站手机站建设公司电话/seo销售是做什么的
1、写代码时用Alt-Insert(Code|Generate…)可以创建类里面任何字段的getter与setter方法。 mac版 是ctrlenter 2、CodeCompletion(代码完成)属性里的一个特殊的变量是,激活Ctrl-Alt-Space可以完成在或不在当前文件里的…...
泉州seo网站推广/郑州seo优化公司
springmvc4.1和springmvc 4.3区别 spring4.1只支持RequestMapping spring4.3支持RequestMapping验证的注解 , 例如 GetMapping 等...
有什的自学做网站/seo月薪
前两天在梅州办事处蛋疼地把ubuntu升级至12.04,结果是网络标识找不到了,而且无线也无法上网了,最简单的检测办法ifconfig没找到eth1(wl的逻辑名)的信息,证明是无线网卡没有驱动,查找系统设置--附加驱动&…...
通用企业网站模板/网络营销的理解
sudo apt-get install libncurses5-dev...
数控技术是学什么/seo自学网app
作者:维吉特伯链接:https://www.zhihu.com/question/49812013/answer/148825073来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。简单地说,根据链式法则,如果每一层神经元对…...
怎么访问被禁止的网站/青岛seo网站建设公司
用于接收父组件传入的参数 简易版——数组的方式定义 props: [size, myMessage] 详细版——对象的方式定义 props: {// 限定参数的数据类型必须为字符串code: String, // 限定参数的类型为字符串型,或数值型 Numberparams2: [String, Number],name:{type:String…...