文章开始,讲个偷来的笑话,何为装饰器呢?
众所周知,每个人都要穿内裤出门,内裤的作用是用来遮羞,但是如果寒风凛冽的冬天到了,我们想要一件东西来御寒,这个时候,可以选择把内裤拉长然后增加保暖功能,但是这样一来,一是麻烦,二是本来最重要的遮羞功能就要打折扣。那么我们人类是怎么办的呢?我们的选择是重新做一条在外面穿的裤子出来,可以穿在不同内裤的外面。
装饰器的作用和刚刚的举例非常像。我们写好了代码,忽然需求方要求我们在每个函数的输出结果上都加一部分功能或者我们需要做一些常规但是每个函数都要执行的功能,比方说打印日志,输入函数的运行时间等,说的全面且专业一些就是:装饰器的强大在于它能够在不修改原有业务逻辑的情况下对代码进行扩展,权限校验、用户认证、日志记录、性能测试、事务处理、缓存等,它能够最大程度地对代码进行复用。
装饰器难以理解之处在于我们对Python万物皆对象以及函数的理解不够深入,装饰器的参数可以是函数,返回值可以是函数,并且函数中还可以调用函数。
我们按照从简单到复杂的程度来看几个装饰器
1.在函数执行时加上日志,最简易版本
#最简易,在函数执行时加上日志
def outer(func):
def inner():
print("日志记录开始")
func()
print("日志记录结束")
return inner
@outer
def foo():
print("foo")
foo()
日志记录开始
foo
日志记录结束
2.对代码进行扩展
def tag(name):
def decorator(func):
def wrapper(text):
value = func(text)
return '<{name}>{value}</{name}>'.format(name=name,value=value)
return wrapper
return decorator
@tag("p")
def my_upper(text):
value = text.upper()
return value
my_upper('hello')
执行结果为:<p>HELLO</p>
3.打印函数执行日志,进阶版
#打印函数执行日志
def log(text):
def decorator(func):
def wrapper(*args, **kw):
# print('%s %s():' % (text, func.__name__))
print('{text} {name}:'.format(text = text,name=func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('execute')
def now():
print('2015-3-25')
now()
execute now:
2015-3-25
4.打印执行的函数名称以及执行时间
import time
def decorator(func):
@functools.wraps(func)
def wrapper(*args,**kw):
start = time.time()
res = func(*args,**kw)
end = time.time()
print('{name}: {time_use}'.format(name=func.__name__,time_use=end-start))
return res
return wrapper
@decorator
def time_test2(x,y,z):
time.sleep(5)
return x+y+z
time_test2(1,6,8)
12
time_test: 3.0001718997955322