阅读本文需要15分钟
前言
装饰器,故名失忆就是装饰用的,它可以装饰函数(其他就不知道了),装饰器用法就是在函数上一句加上
@装饰器名称
装饰器有按功能可分为函数装饰器、类装饰器,按参数分可分为带参数和不带参数,我主要用带参数的函数装饰器
装饰器的应用有:插入日志、性能测试、事务处理、缓存、权限校验。。。(感觉好高大上,我用的只是冰山一角)
栗子
假如我们要测试一个函数xxx的运行时间
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
,我们首先想到在调用函数时⏲一次,调用后再⏲一次,两个时间相减
import time
if __name__ == "__main__":
time.clock()
xxx("{[]}{{}}[]")
print(time.clock())
"""
这里有必要说明一下time.time()是取时间戳
而time.clock()第一次是取程序运行时间,第二次是取上次取时间到这次的间隔。(有点绕,就是第二次直接输出就是程序xxx函数运行时间了)
"""
这样写固然可以,但是以后你会厌倦这种写法,因为每次都要导入
time、前面加
一个函数
,后面加一个函数,以后删除
也麻烦,而且当我们需要测试运行100次
xxx的运行时间呢?在加一个for i in range(100)???,这样做的话又要修改缩进
,实在太烦
但是当你使用了装饰器之后,一切都变得优雅
了。
测试运行xxx所用时间
@timeit
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")
测试运行100次xxx所用时间
@timeit(count=100)
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")
正文
由于装饰器又涉及嵌套函数
闭包
概念,为了简单起见,这些我们略过,按模板来写就好
同样是实现⏲功能
不带参数的函数装饰器
模板
def decorator(func):
def inner(*args , **kwargs):
ret = func(*args , **kwargs) ##这里就是相当于运行了一次下面的some_fun
return ret+1 ##我们将结果+1后返回
return inner
@decorator ##为函数添加装饰器,这个装饰器功能就是给结果+1
def some_fun(arg1 , … ,argn):
return 1
ret = some_fun() ##这里的ret值就是2了
⏲一次
所用时间
def timeit(func):
def inner(*args , **kwargs):
import time
time.clock()
result = func(*args , **kwargs)
return result
print("函数运行时间:{}".format(time.clock()))
return inner
@timeit
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")
带参数的函数装饰器
模板
def decorator(arg = 0):
def outer(func):
def inner(*args , **kwargs):
ret = func(*args , **kwargs)
return ret+1
return inner
return outer
@decorator(arg = 1)
def some_fun(arg1 , … ,argn):
return 1
ret = some_fun()
⏲count次
所用时间
def decorator(count=1):
def outer(func):
def inner(*args , **kwargs):
import time
time.clock()
for i in range(count):
result = func(*args , **kwargs)
print("函数运行{}次时间:{}".format(count, time.clock()))
return result
return inner
return outer
@timeit(count=100)
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")