python总结-装饰器

装饰器

  • 装饰器解决日志问题(分三个版本)
  • 多个装饰器
  • 带参数的装饰器
  • wraps装饰器
  • 内置装饰器
    • property装饰器
    • staticmethod装饰器
    • classmethod装饰器
  • 类装饰器

在这里插入图片描述
概念
装饰器来自 Decorator 的直译。什么叫装饰,就是装点、提供一些额
外的功能。在 python 中的装饰器则是提供了一些额外的功能。

装饰器本质上是一个Python函数(其实就是闭包),它可以让其他
函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返
回值也是一个函数对象。
装饰器用于有以下场景,比如:插入日志、性能测试、事务处理、
缓存、权限校验等场景。

装饰器解决日志问题(分三个版本)

v1.0版本解决

def fun1():print("使用功能1")print("日志记录")
def fun2():print("使用功能2")print("日志记录")

v2.0版本解决

def writeLog():print("日志纪录")
def fun1():print("使用功能1")writeLog()
def fun2():print("使用功能2")writeLog()  

v3.0版本解决

def outfunc(func):def infunc():func()print("日志纪录")return infunc
def fun1():print("使用功能1")
def fun2():print("使用功能2")fun1 = outfunc(fun1)
# 装饰器(闭包)
fun1()

v4.0版本解决,装饰器

def outfunc(func):def infunc():func()print("日志纪录")return infunc
@outfunc
def fun1():print("使用功能1")
@outfunc
def fun2():print("使用功能2")
fun1()
fun2()

修改变量名,见名知意

def mylog(func):def infunc():func()print("日志纪录")return infunc
@mylog
def fun1():print("使用功能1")
@mylog
def fun2():print("使用功能2")
fun1()
fun2()

增加参数处理,可以装饰任意多个参数的函数

 def mylog(func):def infunc(*args,**kwargs):func(*args,**kwargs)print("日志纪录")return infunc@mylogdef fun1():print("使用功能1")@mylogdef fun2(a,b):print(f"使用功能2:{a},{b}")fun1()fun2(100,200)

装饰器本质上是一个Python函数(其实就是闭包),它可以让其他
函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返
回值也是一个函数对象。
装饰器用于有以下场景,比如:插入日志、性能测试、事务处理、
缓存、权限校验等场景。

多个装饰器

有时候,我们需要多个装饰器修饰一个函数。比如:需要增加日志
功能、增加执行效率测试功能。
装饰器函数的执行顺序是分为(被装饰函数)定义阶段和(被装饰
函数)执行阶段的,装饰器函数在被装饰函数定义好后立即执行

在函数定义阶段:执行顺序是从最靠近函数的装饰器开始,自内而外的执行
在函数执行阶段:执行顺序由外而内,一层层执行
import timedef mylog(func):print("mylog start")def infunc():print("日志纪录 start")func()print("日志纪录 end")print("mylog end")return infuncdef cost_time(func):print("cost time start")def infunc():print("开始计时..")start = time.time()func()end = time.time()print(f"耗费时间:{end-start}")return end-startprint("cost time end")return infunc@mylog@cost_time# 相当于:# fun2 = cost_time(fun2)# fun2 = mylog(fun2)# 也相当于:# fun2 = mylog(cost_time(fun2))def fun2():print("使用功能2")time.sleep(2)print("使用功能22")fun2()

执行结果:

cost time start
cost time end
mylog start
mylog end
日志纪录 start
开始计时…
使用功能2
使用功能22
耗费时间:2.004323959350586
日志纪录 end

带参数的装饰器

# coding=utf-8
# 带参数的装饰器的典型写法
def mylog(type):def decorator(func):def infunc(*args,**kwargs):if type=="文件":print("文件中:日志纪录")else:print("控制台:日志纪录")return func(*args,**kwargs)return infuncreturn decorator
@mylog("文件")
def fun2(a,b):print("使用功能2",a,b)
if __name__ == '__main__':fun2(100,200)

wraps装饰器

一个函数不止有他的执行语句,还有着 name (函数名), doc
(说明文档)等属性,我们之前的例子会导致这些属性改变。
functool.wraps 可以将原函数对象的指定属性赋值给包装函数对象,默认
有module、name、doc,或者通过参数选择。

# coding=utf-8
from functools import wraps
def mylog(func):@wraps(func)def infunc(*args,**kwargs):print("日志纪录...")print("函数文档:",func.__doc__)return func(*args,**kwargs)return infunc@mylog   # fun2 = mylog(fun2)
def fun2():"""强大的功能2"""print("使用功能2")if __name__ == '__main__':fun2()print("函数文档--->",fun2.__doc__)"""
运算结果:
日志纪录...
函数文档: 强大的功能2
使用功能2
函数文档---> 强大的功能2
"""

内置装饰器

常用 三种装饰器: property 、 staticmethod 、classmethod 。

property装饰器

property 装饰器用于类中的函数,使得我们可以像访问属性一样来获
取一个函数的返回值。

class User:def __init__(self,name,month_salary):self.name = nameself.month_salary = month_salary@propertydef year_salary(self):return int(self.month_salary)*12
if __name__ == '__main__':u1 = User("gaoqi","30000")print(u1.year_salary)

staticmethod装饰器

staticmethod 装饰器同样是用于类中的方法,这表示这个方法将会是一
个静态方法,意味着该方法可以直接被调用无需实例化,但同样意
味着它没有 self 参数,也无法访问实例化后的对象。

class Person:@staticmethoddef say_hello():print("hello world!")if __name__ == '__main__':Person.say_hello()

classmethod装饰器

classmethod 这个方法是一个类方法。该方法无需实例化,没有 self 参
数。相对于 staticmethod 的区别在于它会接收一个指向类本身的 cls 参
数。

class Person:@classmethoddef say_hello(cls):print(f"我是{cls.__name__}")print("hello world!")
if __name__ == '__main__':Person.say_hello()

类装饰器

上面写的装饰器都是函数来完成的。我们用类也可以实现装饰器。
类能实现装饰器的功能, 是由于当我们调用一个对象时,实际上调
用的是它的 _ _call_ _ 方法。

class Demo:def __call__(self):print('我是 Demo')
demo = Demo()
demo()  # 直接调用对象,实质是调用了他的__call__()

缓存装饰器和计时装饰器综合练习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/327895.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务器GPU温度过高挂掉排查记录

服务器GPU挂掉 跑深度学习的代码的时候发现中断了。通过命令查看: nvidia-smi显示 Unable to determine the device handle for GPU 0000:01:00.0: Unknown Error。感觉很莫名其妙。通过重启大法之后,又能用一段时间。 shutdown -r now但是过了一个小…

我的NPI项目之设备系统启动(二) -- 系统启动阶段和分区的区别

系统启动的就几大阶段: 基于高通平台的Android OS启动过程,简单的说,可以分为一下几个部分: 之前一个比较老的平台大概是这样: 现在比较新的5G平台: 差别在这里,重点了解一下新平台的情况。xb…

如何批量自定义视频画面尺寸

在视频制作和编辑过程中,对于视频画面尺寸的调整是一项常见的需求。有时候,为了适应不同的播放平台或满足特定的展示需求,我们需要对视频尺寸进行批量调整。那么,如何实现批量自定义视频画面尺寸呢?本文将为您揭示这一…

基于SpringBoot的MusiQ音乐网站

目录 前言 开发环境以及工具 项目功能 用户: 后台: 设计详情​编辑 登陆页面 后台管理页面 首页 视频展示 源码获取 前言 本项目是一个基于IDEA和Java语言开基于SpringBoot的MusiQ音乐网站。应用包含管理端,教师端,学生…

Java线程同步机制

第1章:引言 大家好,我是小黑。今天咱们来聊聊并发编程,咱们经常听说并行、并发这些词,特别是在处理大量数据、高用户负载时,这些概念就显得尤为重要了。为什么呢?因为并发编程可以帮助咱们的应用程序更有效…

imgaug库指南(八):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里,数据是模型训练的基石,其质量与数量直接影响着模型的性能。然而,获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此,数据增强技术应运而生,成为了解决这一问题的…

java: 写入数据到HBase

一、添加依赖 <dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.apache.hbase</groupId><art…

【LMM 015】LAMM:多模态指令微调数据集,框架和基准

论文标题&#xff1a;LAMM: Language-Assisted Multi-Modal Instruction-Tuning Dataset, Framework, and Benchmark 论文作者&#xff1a;Zhenfei Yin, Jiong Wang, Jianjian Cao, Zhelun Shi, Dingning Liu, Mukai Li, Lu Sheng, Lei Bai, Xiaoshui Huang, Zhiyong Wang, Jin…

Java面试之集合篇

前言 本篇主要总结JAVA面试中关于集合相关的高频面试题。本篇的面试题基于网络整理以及自己的总结编辑。在不断的完善补充哦。欢迎小伙伴们在评论区发表留言哦&#xff01; 1、基础 1.1、Java 集合框架有哪些&#xff1f; Java 集合框架&#xff0c;大家可以看看 《Java 集…

19道ElasticSearch面试题(很全)

1. elasticsearch的一些调优手段 1、设计阶段调优 &#xff08;1&#xff09;根据业务增量需求&#xff0c;采取基于日期模板创建索引&#xff0c;通过 roll over API 滚动索引&#xff1b; &#xff08;2&#xff09;使用别名进行索引管理&#xff1b; &#xff08;3&…

Unity 一文掌握使用AddListener方法为组件事件添加监听器的方法

在Unity中&#xff0c;很多组件都带有事件&#xff0c;比如: Button组件&#xff1a;onClick() Toggle组件&#xff1a;On Value Changed(Boolean) Dropdown组件&#xff1a;On Value Changed(Int32) InputField组件&#xff1a;On Value Changed(String)、On End Edit(Stri…

HAL——SPI

学习目标 掌握SPI配置方式掌握SPI读写操作 学习内容 需求 SPI配置 打开SPI1,选中全双工模式。观察下方自动生成的引脚&#xff0c;是否和自己开发板引脚对应。 修改引脚&#xff0c;来动右侧芯片引脚视图&#xff0c;找到开发板对应引脚&#xff0c;进行修改。 观察修改后的…