装饰器(decorator):
- 定义了一个函数,想在运行时动态增加功能,又不想改动函数本身的代码。可以起到复用代码的功能,避免每个函数重复性编写代码,简言之就是拓展原来函数功能的一种函数。
- 在python中,装饰器(decorator) 分为
函数装饰器 和类装饰器 两种。 - python中内置的@语言就是为了简化装饰器调用。
列出几个装饰器函数:import functools
- 打印日志:@log
- 检测性能:@performance
- 数据库事务:@transaction
- URL路由:@post(‘/register’)
例子
注意
wrapper 函数的参数传入就是func的参数传入, 既可以使用通用的*args, **kw 一星大斗师和二星大斗师入场, 也可以直接定义
a. 二层套娃
fun执行流程是 Decorator→wrapper→fun
def log(func):
def wrapper(*args, **kw):
print("call %s():", func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print("123")
if __name__ == "__main__":
now()
b. 三层套娃
fun执行流程是 Log→Decorator→wrapper→fun
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('execute')
def now():
print('2015-3-25')
if __name__ == '__main__':
now()
c. fun信息传给wrapper后返回的函数对象成了wrapper
@functools.wraps(func)
import functools
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('execute')
def now():
print('2015-3-25')
print(now.__name__)
def log3(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s():' % (func.__name__))
return func(*args, **kw)
return wrapper
def log2(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log2('execute')
@log3
def now2():
print('hello world')
print(now2.__name__)
if __name__ == '__main__':
now()
print("------------------")
now2()
应用
a. 函数执行时间
import time
import functools
def timeCost(func):
@functools.wraps(func)
def log_time(*args, **kw):
t0 = time.time()
func(*args, **kw)
t1 = time.time()
print(f"function:{func.__name__}, time cost :{t1-t0}")
return t1-t0
return log_time
def timeCost2(unit):
def decorator(func):
@functools.wraps(func)
def log_time(*args, **kw):
t0 = time.time()
func(*args, **kw)
t1 = time.time()
print(f"function:{func.__name__}, time cost :{t1-t0} {unit}")
return t1-t0
return log_time
return decorator
@timeCost
@timeCost2("s")
def test(t):
time.sleep(t)
if __name__ == '__main__':
test(3)
|