类似于想要在函数在运行前打印函数名方便调试程序,这种在函数调用前运行的内容,可以称之为函数的装饰,而实现装饰的函数可以称之为装饰器。
首先自己定义一个函数:
def now(*args,**kw):
print(args)
print('2018-1-5')
想要now函数print之前打印函数名可以的做法:
def decorator(fun):
print('call %s'%fun.__name__)
return fun()
接下去再执行:
decorator(now)
但是这样有几个问题:1)整个代码就会变得全是decorator;2)当原函数带有参数时无法调用。
因此装饰器产生了定义如下:
def decorator(fun):
def wrapper(*args,**kw):
print('call %s'%fun.__name__)
return fun(*args,**kw)
return wrapper
只需在函数调用前加上@decorator,其作用相当于 now = decorator(now),且同时可以带上now的参数:
@decorator
now(location='Beijing')
------ ====== -------
() {location: 'Beijing'}
call now():
2018-1-5
倘若decorater自身也想要带参数则只需要将其封装,传入参数,则需要:
def argdec(*args):
def decorator(fun):
def wrapper(*args,**kw):
print('call %s'%fun.__name__)
return fun(*args,**kw)
return wrapper
return decorator
调用时则需要:
@argdec()
now()
--- === ---
(){}
call now()
2018-1-5
@argdec()相当于 now=argdec()(now)。
存在now函数被重新定义的过程,所以now.__name__='wrapper'。为了防止程序出错可以在装饰器内嵌函数之前写入wrapper.__name__=fun.__name__,亦可导入funtools模块,调用其中@functools.wrps(fun)即可起到相同作用。