装饰器简介
实质: 是一个函数
参数:是你要装饰的函数名(并非函数调用)
返回:是装饰完的函数名(也非函数调用)
作用:为已经存在的对象添加额外的功能
特点:不需要对对象做任何的代码上的变动
应用场景:插入日志、性能测试、事务处理、权限校验等
简单用法如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# *arg,**kw 表示所有任意参数
def test(func):
def printname(*arg,**kw):
print('this is 装饰器')
return func(*arg,**kw)
return printname
def ceshi():
print('我是ceshi函数')
ceshi()
>>>>
this is 装饰器
我是ceshi函数
原理
把@test
放到ceshi()
函数的定义处,相当于执行了语句
ceshi = test(ceshi)=printname
所以 ceshi()=printname()
高阶装饰器
带参数
1 | def log(text): |
和两层不同的是三层的执行顺序如下
now = log(‘execute’)(now)
参数是now函数,返回值最终是wrapper函数,函数也是对象,它有name等属性,它们的name已经从原来的’now’变成了’wrapper1
2 now.__name__
'wrapper'
Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下1
2
3
4
5
6
7
8
9
10import 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
实践案例
请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import time
import functools
def ddq(text):
def say(func):
def deco(*args, **kw):
print(text, func.__name__, time.ctime())
return func(*args, **kw)
return deco
return say
def test():
print('this is test')
>>>> test()
ed test Tue Mar 19 18:11:09 2019
this is test