回顾

  上一节我们进行了Python简单装饰器的讲解,但是python的装饰器还有一部分高级的使用方式,这一节就针对python装饰器高级部分进行讲解。

为一个函数添加多个装饰器

  今天,老板又交给你一个任务,老板说:"之前的装饰器用用起来挺好,但是这次我需要再次添加更多的参数,这个任务就交给你了,好好干。",这种时候,我们就可以针对一个函数使用多个装饰器。

import datetime

def hel(func):
def inner(*args,**kwargs):
r = func(*args,**kwargs)
print('bye')
return r
return inner def hel1(func):
def inner(*args,**kwargs):
print('start time:%s' % datetime.datetime.now())
r = func(*args,**kwargs)
print('end time:%s'%datetime.datetime.now())
return r
return inner @hel1
@hel
def f1(name):
print('hello')
print(name) name = 'alexsel'
f1(name) 执行结果:
start time:2018-07-01 10:36:02.085027
hello
alexsel
bye
end time:2018-07-01 10:36:02.086027

这次我们在对之前代码添加数据的时候,我们写了第二个装饰器,我们使用这个装饰器针对之前的函数再次增加新的功能,输出了开始结束时间。

代码及输出问题解析

针对刚才多个装饰器,我们需要了解的是在进行输出的时候是怎么进行输出的,首先装饰器函数hel首先对f1函数进行装饰,然后装饰器函数hel1在对被hel装饰过函数进行装饰,最后执行两次装饰过的函数。在新添加的装饰器中(hel1)的func所指的函数是已经被hel装饰过的函数。

带参数的装饰器

  装饰器在调用的时候可以传入相应的参数,传入参数以后我们可以根据不同的参数,针对函数进行相应信息输出。

def use_log(level):
def hel(func):
def inner(*args,**kwargs):
if level == 'warning':
print('The current function:%s'%func.__name__)
r = func(*args,**kwargs)
return r
return inner
return hel @use_log(level = 'warning')
def f1(name):
print('hello')
print(name) f1(name = 'alexsel') 输出结果:
The current function:f1
hello
alexsel

上面的代码就是可以带有参数的装饰器,就是将以前我们使用简单的装饰器进行了一次封装,当我们调用函数的时候,python可以将我们定义的装饰器的参数传入函数中。

基于类的装饰器

  讲解python的类装饰器需要用到python类的知识,python的类我们还没有进行学习,就先简单了解一下。

  根据我们刚才对装饰器的学习,我们发现装饰器如果需要正常运行,装饰器所接受的对象必须是可调用的,然后在装饰器内部在返回一个可调用的对象,一般情况下,可调用的对象都是函数,特殊情况是对象中写入了__call__()方法就也是可以调用的对象。

class Test():
def __call__(self):
print('test') te = Test()
te() 输出结果:
test

我们是有类装饰器的时候,可以让类的构造函数__init__()接受一个函数,然后重载一个__call__()并且返回一个函数,来达到装饰器的目的。

class Test():
def __init__(self,func):
self.func = func def __call__(self,*args,**kwargs):
print('The current function:%s' % self.func.__name__)
return self.func() @Test
def tes():
print('obj') tes() 输出结果:
The current function:tes
tes

装饰器就是对原来函数、对象功能的扩展,相当于对函数重新封装,重点需要理解的是装饰器中返回的是函数,而且装饰器所装饰器的对象也需要是可调用的。今天装饰器的高级部分就到这里。

最新文章

  1. [CentOS] 指定命令别名:Alias & 软链接生成命令 ln -s
  2. silverLight--绑定数据dataGrid
  3. 高仿Windows Phone QQ登录界面
  4. 重构第1天:封装集合(Encapsulate Collection)
  5. javaScript基础练习题-下拉框制作(CSS)
  6. UrlConnection连接和Socket连接的区别
  7. Linux Shell脚本入门--(linux空设备文件和重定向)>/dev/null 2>&1
  8. JAVA_build_ant_cmd pass muti param
  9. DefaultHttpClient is deprecated 【Api 弃用]】
  10. Windows中安装jdk,出现javac不是内部或外部命令 也不是可运行的程序
  11. 微信小程序的网络设置,及网络请求:wx.request(OBJECT)
  12. WAF开放规则定义权:专家策略+用户自定义策略=Web安全
  13. 无需sendmail:巧用LD_PRELOAD突破disable_functions
  14. linux服务器开机启动tomcat
  15. HTTP 协议常见首部字段
  16. BZOJ.5093.[Lydsy1711月赛]图的价值(NTT 斯特林数)
  17. kafka的log存储解析——topic的分区partition分段segment以及索引等(转发)
  18. android4.0 中关于内外置sd卡的获取及读写权限问题
  19. 2018牛客网暑期ACM多校训练营(第二场) J - farm - [随机数哈希+二维树状数组]
  20. Dynamics CRM 2011 快速查找 出现异常 QuickFindQueryRecordLimit exceeded. Cannot perform this operation 的解决方法

热门文章

  1. Android笔记——Socket通信实现简单聊天室
  2. mysqldump导出sql文件中insert多行问题
  3. python filter&sorted
  4. nginx知识图谱
  5. mysql配置远程登录
  6. js获取昨天今天和明天
  7. CentOS查看线程、硬盘、内存、cpu、网卡
  8. luogu P2016 战略游戏
  9. AngularJS简介-起步阶段
  10. 【题解】洛谷P2704 [NOI2001] 炮兵阵地(状压DP)