1、装饰器decorator概念

  • 在不改变原有函数代码,且保持原函数调用方法的基础上,给原函数增加新的功能(给类增加属性或方法)
  • 用一个函数或类去装饰一个旧函数(或类)造出一个新函数(或新类)
  • 在原有的函数上加上@符,装饰器会吧线面的函数当作参数传递到装饰器中,@符又称之为语法糖
  • 应用场景:引入日志,函数执行时间统计,执行函数前的准备工作,执行函数后的处理工作,权限校验缓存等

2、装饰器的原型

描述器扩展属性,装饰器扩展方法(这句弹幕里看到的)
利用闭包,把函数当作参数传递,并且在函数内去调用传递进来的函数,并返回一个函数

传统用法

#定义一个闭包函数(外函数),有一个f形参,作为要向这个参数传递的参数
def outer(f):#定义内函数,并在内函数中调用了外函数的参数def inner():print('我是外函数中的内函数1')f()print('我是外函数中的内函数2')return inner#定义一个普通的函数
def old():print('我是一个普通函数')old=outer(old)#outer返回了inner函数,赋值给了old
old()#实际调用的是inner函数

结果是:

我是外函数中的内函数1
我是一个普通函数
我是外函数中的内函数2

装饰器用法

#定义一个闭包函数(外函数),有一个f形参,作为要向这个参数传递的参数
def outer(f):#定义内函数,并在内函数中调用了外函数的参数def inner():print('我是外函数中的内函数1')f()print('我是外函数中的内函数2')return inner#定义一个普通的函数
#增加装饰符
@outer#实际就是把old装进了outer,old函数作为outer函数的实参传给了outer
def old():print('我是一个普通函数')
old()#实际调用的是inner函数

结果是:

我是外函数中的内函数1
我是一个普通函数
我是外函数中的内函数2

3、案例-统计函数执行时间

#装饰器应用场景-统计函数执行时间
import time#定义一个统计函数执行时间的装饰器
def runtime(func):def inner():start=time.perf_counter()func()end=time.perf_counter()-startprint(f'函数的调用执行时间为:{end}')return inner
@runtime
def func():for item in range(1,10):print(item,end=' ')time.sleep(0.5)func()#1 2 3 4 5 6 7 8 9 函数的调用执行时间为:4.504389300000001

4、装饰器的嵌套

1、先使用离得近的outer装饰器,装饰love函数,返回了一个inner函数
2、再使用上面的扩展装饰器,装饰上一次返回的inner函数 ,有返回了kzinner函数

#外函数
def outer(func):def inner():print('find somebody to talk')func()print('talk with him at a place')return inner#再定义一个装饰器
def kuozhan(func):def kzinner():print('扩展1')func()print('扩展2')return kzinner
#扩展的嵌套,这里装饰符的先后,决定了嵌套的顺序,进而决定了执行语句的顺序
@kuozhan
@outer
def love():print('falling love with somebody')love()

结果为:

find somebody to talk
扩展1
falling love with somebody
扩展2
talk with him at a plac

5、装饰器带有参数的函数

如果装饰带有参数的函数,需要在内函数中定义形参,并传递给调用的函数,因为调用原函数等于调用内函数

#定义一个装饰器
def outer(func):#如果装饰带有参数的函数,需要在内函数中定义形参,并传递给调用的函数,因为调用原函数等于调用内函数def inner(person):print('找到一个人')func(person)print('找一个地方')return inner#使用装饰器
@outer
def love(name):print(f'和{name}一起畅谈人生')love('思思')

6、装饰带有多参数的的函数

# 定义一个装饰器
def outer(func):# 如果装饰带有参数的函数,需要在内函数中定义形参,并传递给调用的函数,因为调用原函数等于调用内函数def inner(who, name, *args, **kwargs):print('找到一个人')func(who, name, *args, **kwargs)print('找一个地方')return inner# 使用装饰器
@outer
def love(who, name, *args, **kwargs):print(f'{who}和{name}一起畅谈人生')print('然后去吃了好多美食', args)print('看了一场电影', kwargs)love('思思','三多','火锅','辣条','麻辣烫',moive='速度与激情')

结果

找到一个人
思思和三多一起畅谈人生
然后去吃了好多美食 ('火锅', '辣条', '麻辣烫')
看了一场电影 {'moive': '速度与激情'}
找一个地方

7、带有参数的装饰器

如果装饰器需要有参数,那么应该给当前装饰器套个壳,用于接收装饰器的参数

# 定义一个装饰器
# 如果装饰器需要有参数,那么应该给当前装饰器套个壳,用于接收装饰器的参数
def kuozhan(person):def outer(func):def inner1():print('找到一个人')func()print('找一个地方')def inner2():print('找到另外的一个人')func()print('找一个也许还蛮有意思的地方')#装饰器壳的参数,用于在函数内去做流程控制if person == '高富帅':return inner1else:return inner2return outer# 使用装饰器,装饰器带参
@kuozhan('高富帅')  # 使用套壳的装饰器名称
def love():print('一起畅谈人生')
love()
print('****')
@kuozhan('矮穷矬')  # 使用套壳的装饰器名称
def love():print('一起畅谈人生')
love()

结果:

找到一个人
一起畅谈人生
找一个地方
****
找到另外的一个人
一起畅谈人生
找一个也许还蛮有意思的地方

8、类装饰器装饰函数

Outer()得到一个obj @obj得到obj(love)然后再执行call(love)最后调用inner()

# 定义一个装饰器
class Outer():#当把该类的对象当作函数调用时,自动触发obj()def __call__(self, func):self.func=func#把传进来的函数当作对象的成员方法return  self.inner#返回一个闭包(函数)#在定义的需要返回的新方法中,去进行装饰和处理  def inner(self,person):print('找一个人')self.func(person)print('找一个地方')# 使用装饰器
@Outer() #Outer()得到一个obj @obj得到obj(love)然后再执行call(love)最后调用inner()
def love(person):print(f'和{person}一起畅谈人生')
love('张三丰')#实际调用的事装饰器里的inner函数
print(love)#此时love就是Outer类中的inner方法。<bound method Outer.inner of <__main__.Outer object at 0x000001F4D7C4C460>>

9、用类方法装饰函数

到目前为止,所有的形式的装饰器,包括函数装饰器,类装饰器,类方法装饰器,都有一个共同特点:都是在给函数进行装饰,增加功能

还有一种装饰器,是专门装饰类的,也就是在类的定义的前面是用@装饰器这种语法

# 定义一个装饰器
class Outer():def newInner(func):Outer.func = funcreturn Outer.innerdef inner():print('找到一个人')Outer.func()print('约到一个地方')# 使用装饰器
@Outer.newInner  # 使用Outer.newInner(love)==>Outer.inner
def love():print('和志同道合者一起畅谈人生')love()#love()=>Outer.inner()

10、用函数装饰器装饰类

还有一种装饰器,是专门装饰类的,也就是在类的定义的前面是用@装饰器这种语法
装饰器给类装饰,目的是为了不改变类的定义和调用的情况下给类增加新的成员(属性或方法)

# 定义一个函数装饰器,给类增加新的属性和方法
def kuozhan(cls):def func2():print('我是在装饰器中追加扩展的新方法,func2')#把刚才定义的类赋值给类cls.func2=func2#再添加一个新属性cls.name='我是装装饰器添加的新属性name'#返回时,吧追加类新成员的类返回去return cls#使用装饰器
@kuozhan
class Demo():def func():print(' 我是demo类中定义的func方法')Demo.func()#此时调用的Demo类是通过装饰器修改过的类
Demo.func2()#装饰器新添加的方法
print(Demo.name)#装饰器新添加的属性

结果

 我是demo类中定义的func方法
我是在装饰器中追加扩展的新方法,func2
我是装装饰器添加的新属性name

11、用类装饰器装饰类

# 定义一个类装饰器,给类增加新的属性和方法
class kuozhan():def __call__(self, cls):#把接受的类,赋值给当前对象,作为一个属性self.cls=cls#返回一个函数return self.newFuncdef newFunc(self):self.cls.name='我是在类装饰器中添加的属性name'self.cls.func2=self.func2#返回传递进来的实例化结果,obj,返回的是一个对象,self.cls(),因为self.cls是传进来的类return self.cls()def func2(self):print('我是在类装饰其中追加的方法func2')#使用类装饰器
@kuozhan()#kuozhan()=》obj==》@obj(Demo)==》__call__(Demo)==>newfunc
class Demo():def func(self):print(' 我是demo类中定义的func方法')obj=Demo()#Demo()=newFunc()==>obj
obj.func()
obj.func2()
print(obj.name)
print(obj)#此时的obj依然是Demo类的实例化对象,只不过经过装饰后,增加了新的属性和方法

结果

 我是demo类中定义的func方法
我是在类装饰其中追加的方法func2
我是在类装饰器中添加的属性name
<__main__.Demo object at 0x000001AFB370B400>

Python(IT峰)笔记12-装饰器概念,装饰器的原型,装饰器的嵌套,装饰带有参数的函数,装饰器的嵌套,装饰带有多参数的函数,带有参数的装饰器,用类方法装饰函数,用韩式装饰器装饰类,用类装饰器装饰类相关推荐

  1. python基础学习笔记12:Python面向对象编程

    面向对象编程思想 1.什么是面向过程 传统的面向过程的编程思想总结起来就八个字--自顶向下,逐步细化! 将要实现的功能描述为一个从开始到结束按部就班的连续的"步骤" 依次逐步完成这 ...

  2. pythonsparkpickle_Learning Spark (Python版) 学习笔记(一)----RDD 基本概念与命令

    <Learning Spark>这本书算是Spark入门的必读书了,中文版是<Spark快速大数据分析>,不过豆瓣书评很有意思的是,英文原版评分7.4,评论都说入门而已深入不足 ...

  3. 【Python爬虫学习笔记12】Ajax数据爬取简介

    有时候在我们设计利用requests抓取网页数据的时候,会发现所获得的结果可能与浏览器显示给我们的不一样:比如说有的信息我们通过浏览器可以显示,但一旦用requests却得不到想要的结果.这种现象是因 ...

  4. Python入门学习笔记——12.文件操作

    ##################################################### # 1.文件写入 # 写入操作 ''' 1.打开文件 open()参数1:文件路径路径 ur ...

  5. python类的魔法方法和装饰器

    装饰器 闭包装饰器 装饰器的本质就是一个闭包, 闭包三要素:1 函数嵌套, 2 外部函数返回内部函数的引用, 内部函数使用外部函数的变量 1 使用装饰器简单实现一个登录校验功能 In [1]: use ...

  6. Python笔记_23_正则相关函数_类中的方法_装饰器_异常

    文章目录 正则相关函数 search 和 match split 切割 sub 替换 finditer 匹配字符串中相应内容,返回迭代器 compile 指定一个统一的匹配规则 正则表达式的修饰符 类 ...

  7. python 类的使用(5)之类装饰器(类的装饰器和类作为装饰器)

    在阅读博客中,发现了类装饰器的存在,由于之前就在写类相关的专栏,这次就赶紧补上之前的内容啦.类装饰器这个词是有歧义的,因为类本身可以作为装饰器,一个类也可以被函数装饰器所装饰.今天就简单介绍一下这两种 ...

  8. 装饰器/使用类和对象封装一个工具类

    # coding:utf-8 # 装饰器是以@开头,@结构称为语法糖,装饰器的作用主要是给现有的函数增加一些额外的功能. # @classmethod # @staticmethod # @prope ...

  9. 类中的三个装饰器方法

    @classmethod class A:__count = 0 #隐藏count属性def __init__(self,name):self.name = nameself.__add_count( ...

最新文章

  1. 【项目实践】基于Mask R-CNN的道路物体检测与分割(从数据集制作到视频测试)...
  2. PHP中单引号和双引号的区别
  3. 系统集成项目管理工程师-项目沟通管理笔记
  4. 网站跳出率的相关要点介绍
  5. QT子线程与主线程的信号槽通信
  6. 呀~ 一个.java的源文件可以写这么多类啊
  7. wxpython实现简单图书管理系统
  8. python批量读取csv并入库pg_如何通读CSV然后在Python中发布批量API调用
  9. python报表自动化系列 - 译码:将纯数字译码为Excel列坐标的字母索引表示形式
  10. Zephry I2C和SPI驱动器介绍和操作FM24V10闪存
  11. [转]Python中RE模块的应用
  12. java官方网站下载_java下载 7.0 官方版
  13. windows server 2003 系统提权
  14. 【T1】飞跃专业版库存期初无法同步到【U+】通用财务
  15. linux中查看rpm包位置,linux中,查看某个命令是来自哪个RPM包或者是通过哪个RPM包安装的...
  16. js 时间转换、 向上保留两位小数
  17. Linux 系统Error starting userland proxy: listen tcp4 0.0.0.0:xx端口: bind: address already in use的端口占用问题
  18. html 圆角矩形,圆角矩形
  19. idea设置黑色经典样式Darcula
  20. 客户端性能优化实战经验分享

热门文章

  1. 【计算机】ELF文件和BIN文件
  2. mysql 导入pdb_12c pdb的数据泵导入导出简单示例
  3. Comunion 区块链深度学习系列|区块链基本原理
  4. 并发并行多线程多进程协程
  5. 从自媒体转做电商,实操店铺单月净利润4W+经验
  6. 微信小程序+VUE社区疫情防控(含源码+论文+答辩PPT等)
  7. uniapp的uni_modules目录需要提交到Git吗?为什么有了node_modules,还需要再发明一个uni_modules的轮子?node_modules和uni_modules的区别
  8. ThinkServer RD450 2008R2 64位 驱动备份,这是用360驱动大师备份的驱动。
  9. rust显卡要求 steam_rust腐蚀游戏配置要求是什么,腐蚀Rust配置要求汇总
  10. 如何计算两幅图像的相似度,计算两张图片相似度