之前写Flask应用的时候就用过,但是无奈那时候水平太低,还没有研究到这里。最近我就决定把Python的这些高级概念全部研究清楚先。
在代码运行期间动态增加功能的方式,称为装饰器。一个装饰器的定义类似于闭包,也有可能是一个返回函数的高阶函数。比如定义一个装饰器函数:
def log(func):
#内部函数可以使用func
def wrapper(*args,**kw):
print("call %s()"% func.__name__)
return func(*args,**kw)
return wrapper
#使用语法糖来定义一个有装饰器的函数
@log
def now():
print("2014")
#另外被装饰器装饰的函数的__name__会发生改变
print(now.__name__)
#输出wrapper,因为相当于这样调用
#log(now) 返回的是wrapper函数```
由于上述原因,有些依赖函数签名的代码执行就会出错,所以需要将now的\_\_name\_\_变量赋值给wrapper,使用functools.wraps来实现这一点:
import functools
def log(func):
#相当于调用wraps(func)(wrapper)
#这样就将wrapper的name变量转变成func.name
@functools.wraps(func)
def wrapper(args,kwargs):
print('call %s():' % func.name)
return func(args,**kwargs)
return wrapper
@log
def now():
print("2014")
输出now
print(now.name)```
下来编写一个如果decorator本身需要传入参数的装饰器函数,这个函数就必须是一个返回decorator的高阶函数。
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
#log('execute')返回时decorator
#所以就相当于调用decorator(now)
#因此在定义decorator的下面那个函数下写
#functools.wraps(func)
@log('execute')
def now():
print("2014")```
下面是完整的一个,改变wrapper的\_\_name\_\_变量的函数定义。
def log1(text):
def decorator(func):
@functools.wraps(func)
def wrapper(args,kwargs):
print("%s %s():"%(text,func.name))
return func(args,**kwargs)
return wrapper
return decorator
@log1('execute')
def now():
print("2014")
print(now.name)
now()```