装饰器是程序开发的基础知识,用好装饰器,在程序开发中能够提高效率

它可以在不需要修改每个函数内部代码的情况下,为多个函数添加附加功能,如权限验证,log日志等

涉及点:

1.先梳理一下

>>> deffun():print(‘Fun...‘)#fun 是函数#fun() 是执行函数

#A

>>> deftest():print(1)>>> deftest():print(2)#B

>>>test()2

>>>

重复定义函数不会报错

只是会让函数名指向不同的函数体

>>> deftest():print(‘TEST‘)>>> deffun():print(‘FUN‘)>>> test=fun #test改变指向,指向了和fun一样的函数体

>>>test()

FUN>>>

在C和C++中,会告诉你两个函数重名了,在Python中不会,会默认改变指向

2.开放封闭原则

开放:对扩展开发

封闭:已实现的功能代码块

1.添加新需求,最好不要改动原来的代码块,因为别处已经调用的地方可能会报错,

尽可能进行扩展

2.开发的时候,别轻易删除代码

3.现有fun1,fun2函数,在每次调用这两个函数时,需要进行权限验证

>>> deffun1():print(‘fun1‘)>>> deffun2():print(‘fun2‘)>>> deftest(fun):definner():print(‘验证‘)

fun()returninner>>> mytest=test(fun1)>>>mytest()

验证

fun1>>>

不是直接在每个需要加验证的函数里面修改,那样违反了 开放封闭 原则

而是创建一个闭包:

test的参数在内部函数中被调用,被调用时,先执行验证功能。传入的参数决定了是哪个函数

所以即可以传入fun1,也可以传入fun2

上面的代码虽然添加了验证功能,在不改变原有代码部分的情况下。

但每次调用不是直接调用原来的fun1 、fun2;而是调用另一个函数

现在改变一下代码:

>>> deffun1():print(‘fun1‘)>>> deffun2():print(‘fun2‘)>>> deftest(fun):definner():print(‘验证功能‘)

fun()return inner

>>> fun1=test(fun1) # 现在能够通过原有函数名直接调用,不改变原有函数代码

>>> fun1()

验证功能

fun1

>>>

如何解释上述代码?

其实只是改变了函数名对函数体的引用

执行fun1=test(fun1)时,test中的fun参数指向了fun1的函数体。inner中,执行了fun:fun()。现在让fun1改变它的指向,让它指向inner

所以调用fun1就是调用inner函数

简言之:通过改变引用,让inner函数里面既包含新功能,也包含了旧功能

然后改变原来函数名的指向,让它指向inner函数。

但是,每次都需要这么写:fun1=test(fun1) 过于麻烦

4.使用语法糖:

在fun1前面加 @test 等价于 fun1=test(fun1)

>>> deftest(fun):definner():print(‘验证功能‘)

fun()returninner>>>@testdeffun1():print(‘fun1‘)>>>fun1()

验证功能

fun1>>>

装饰器:在原有的基础上,不改动原先代码,然后添加新的功能,进行装饰(Python特有)

5.例子

执行结果:

这类代码应该怎么看?

如14~16行代码,把test1的功能「给」makeBold里的fn

把执行test1当成执行makeBold里的wrapped函数

test3添加了两个装饰器,为什么结果是hello world-3

6.两个装饰器装饰过程:函数test3为例

装饰器@makeBold下面是装饰器@makeItalic,需要等装饰器@makeItalic将test3进行装饰之后

返回一个新的引用,再进行装饰,所以此时装饰器@makeBold没有被执行,先执行装饰器@makeItalic

1. @makeItalic:test3=makeItalic(test3) 此时test3指向新引用,makeItalic中的wrapped

2.@makeBold:test3=makeBold(test3)此时传入的test3为@makeItalic装饰后新的test3

此时,test3指向了@makeBold中的wrapped,@makeBold中的fn指向了@makeItalic中的wrapped,@makeItalic中的fn指向了原来test3的函数体。

倒着装,顺着执行

7.装饰器什么时候进行装饰?

在定义的时候就进行装饰,不是等到调用才装饰

>>> deffun(fn):print(‘正在装饰...‘)definner():

fn()returninner>>>@fundeftest():print(‘函数‘)

正在装饰...>>>

上述情况是没有参数的情况下进行

8.现在看一下有两个参数的情况

因为(原函数)test需要两个参数,所以在调用经过装饰器装饰的test时也要传入两个参数,

这两个参数经过inner,fn传入(原函数)test的函数体

但是,被装饰的函数形参发生变化时,都需要改变「装饰器」函数的形参吗

9.不定参数

使用不定参数,这样不管被装饰的函数形参怎么变化,装饰器会自动匹配,只需要更改被装饰的函数的代码就可以

如:

函数test的形参由2个增加到3个:

函数test的形参由3个改为没有:

10.被装饰的函数有返回值的情况

打印结果:None

由于fn()返回的结果没有被inner返回,所以打印test时为None

修改:

执行fn()时,执行的是第10行test里面的代码,返回了一个字符串,这个字符串,也就是fn的返回值

在inner被变量rn接收,inner又返回了变量rn。

11.通用装饰器

运行结果:

...

None

...

test2

...

vaule: 10

...

vaule: 10 20 30

通用的装饰器,同时满足了多种函数的情况,有无参、多参、有无返回值等

当函数没有返回值时,inner函数中的变量ret接收到None

inner的形参为*args、**kwargs为不定参

12.带参数的装饰器

python核心装饰_Python核心编程 | 装饰器相关推荐

  1. python高级语法装饰器_Python高级编程——装饰器Decorator超详细讲解上

    Python高级编程--装饰器Decorator超详细讲解(上篇) 送你小心心记得关注我哦!! 进入正文 全文摘要 装饰器decorator,是python语言的重要特性,我们平时都会遇到,无论是面向 ...

  2. python高性能写法_python高性能编程方法一

    阅读 Zen of Python,在Python解析器中输入 import this. 一个犀利的Python新手可能会注意到"解析"一词, 认为Python不过是另一门脚本语言. ...

  3. python udp通信_Python网络编程(三)

    回顾 在<Python进阶记录之网络编程(二)>中,我们介绍了UDP端口号的基本概念和作用以及Python中UDP服务端的端口绑定和简单创建.今天我们利用UDP server和UDP cl ...

  4. python三大器_python三大器(装饰器/生成器/迭代器)

    1装饰器 1.1基本结构 def 外层函数(参数): def 内层函数(*args,**kwargs); return 参数(*args,**kwargs) return 内层函数 @外层函数 def ...

  5. python核心数据类型_Python核心数据类型-列表

    Python核心数据类型-列表 关于列表的重要属性 列表是任意对象的有序集合,列表中可以包含任何种类的对象,数字 字符串 或者是其他列表 列表可以通过偏移来读取其中的元素,也可以通过分片读取列表中的某 ...

  6. python核心数据类型_Python核心数据类型—元组

    Python核心数据类型-元组 Python元组与列表类似,但是元组属于不可变类型 创建元组 a = () #创建空元组 a = (1, 2, 3) #创建一个元组 a = [1, 2, 3] b = ...

  7. python的核心数据类型_Python核心数据类型-集合

    Python核心数据类型-集合 特点 确定性 互异性 无序性 len() ##返回集合的长度 #判断元素是否在集合中 In [80]: x = set([1,2,3,4]) In [81]: 1 in ...

  8. python核心教程_python核心教程--第四章

    第四章讲的是python对象. 4.1 python对象 所有的python对象都拥有三个特性:身份,类型和值 身份: 每一个对象都有一个唯一的身份标识自己,任何对象的身份可以使用内建函数id()来得 ...

  9. python核心数据类型_Python核心数据类型——字符串

    字符串 Python的字符串是一个有序的字符集合,有序指的是可以通过偏移来访问每个字符,每个字符有严格的从左到右的位置顺序,类似于数组.Python中没有单个字符的类型(C语言中的char),取而代之 ...

最新文章

  1. 函数声明与函数表达式
  2. Linux EOF使用
  3. 64位服务器IIS不能识别32位framework版本。IIS没有Asp.net切换界面的解决办法。
  4. Android studio2.3.3升级3.1.2坑
  5. 表单中的重置与取消按钮
  6. oracle 级联外键约束,Oracle 外键的相关约束中级联删除的方案
  7. 地址后面的sessionid怎么消除_大朗饭店消除蟑螂帮您识别隐蔽鼠迹
  8. CAS单点登录系列之原理简单介绍
  9. 史上最全的自动驾驶研究报告(上)
  10. 【bzoj1984】【坑】月下“毛景树” 树链剖分
  11. 爬取网易云数据并且可视化展示
  12. 榆熙电商:为什么“砍价免费拿”是拼多多主推的一个营销项目?
  13. html中怎么让text不换行,css如何让文本不换行?
  14. 403错误(已解决)
  15. python自动获取某网站二次元图片下载
  16. python代码图片头像_python图像处理-个性化头像
  17. OnlyBill 简易记账软件(续)
  18. CSS系列之详解overflow
  19. 垂直水平居中的几种方式
  20. 红米2联通4G版_标注:2014811_官方线刷包_救砖包_解账户锁

热门文章

  1. Visual Studio 2008 使用小技巧
  2. SCCM部署(四)---ADSI修改
  3. 山西流感就诊比持续上升 专家为民答疑解惑
  4. ogr2ogr: Export Well Known Text (WKT) for one feature to a CSV file
  5. C#利用Attribute实现简易AOP介绍 (转载)
  6. 用户第一次登录后要求修改密码
  7. IBM投资4000万美圆,加强对SAP®应用的支持
  8. Linux命令(持续更新)
  9. 《javascript高级程序设计》笔记:变量对象与预解析
  10. iOS唯一标示符引导