装饰器详解
一、背景
基于python中一切皆对象的思想,其通常作为函数的函数类型出现。
二、关于函数
函数有以下特性:
1、可以在其中定义另一个函数;
2、可以将其作为参数传递;
3、可以将其作为返回值返回;
函数也是作为对象存在的。
三、语法糖
在计算机科学中,可以使得编程语言更加容易的表达一个操作的语法,使得程序员代码变得具有可读性,使得操作变得更加的清晰、方便。
****注:装饰器是一种语法糖。
四、装饰器类型
装饰器可大致分为以下几类:
1)无参数的装饰器;
2)带参装饰器;
3)类装饰器;
4)装饰类方法;
五、装饰器意义
装饰器可以让其他函数代码在无需做任何代码变动的前提下,提供额外的功能。
装饰器通常用于有切面需求的场景下,例如:
插入日志、性能测试、事务处理、缓存、权限校验等场景;
可以通过装饰器抽离出大量与函数本身无关的大量代码并加以重用,提高代码复用率。
六、简单实现
此处实现一个简单的装饰器,用于做代码调试打印日志功能:
import time
'''
简单装饰器,打印日志
'''
def My_Debug(func):
def show(*args,**kw):
print('开始函数:{}'.format(func.__name__))
#函数真正执行部分
time1=time.time()
print('执行结果:{}'.format(func(*args,**kw)))
time2=time.time()
print('结束函数:{}'.format(func.__name__))
print('执行耗时:{}'.format(time2-time1))
return show
'''
带参装饰器
'''
def My_Debug2(str,contry):
def funcc(func):
def show2(*args,**kw):
print('装饰器2开始\n','-------------')
if contry=='输出':
print(str)
if contry=='反转':
print(''.join(reversed(str)))
print('执行结果:{}'.format(func(*args, **kw)))
print('装饰器2结束\n', '-------------')
return show2
return funcc
@My_Debug2('12345','反转')
@My_Debug
def myprint(str):
time.sleep(5)
return len(str)
if __name__=='__main__':
str='123456'
myprint(str)
代码注释完整,不做赘述。可以直接复制本地调试。
七、关于执行顺序
关于装饰器的执行顺序,按照上面代码作为讲解。首先需要知道,装饰器是就近先装饰的,意思是上述代码My_Debug先装饰函数myprint,然后由My_Debug2装饰函数体。但是运行中可看到My_Debug2装饰器先执行,My_Debug后执行。这种现象的解释为:装饰器是由内向外逐层装饰,而执行过程为由外向内逐层执行。