python中decorator
先讲一下python中的@符号
看下面代码
@f @f2 def fun(args, args2, args3, args4, ……): pass
上面代码相当于
def fun(args, args2, args3, args4, ……): pass fun = fun(f2(fun))
def now(): print('2016-06-03') n = now n2 = now() n2 #2016-06-03 n() #2016-06-03 #函数对象有一个name属性,可以拿到函数的名字 print(n.__name__) #n这个变量指向的函数名为now,输出结果为now def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper @log def now(): print('2016-06-03') now() #如果decorator本身需要传入参数,那就要编写一个返回decorator的高阶函数,比如自定义log的文本: 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('rain:') def now(): print('2016-06-03') now() #但是像上面那样优化,装饰后的函数的__name__已经从now变成了wrapper print(now.__name__) #可以看到now这个名字已经被改成了wrapper #为了防止依赖于签名的那些函数执行时出错,要把原来函数的__name__复制到wrapper中 import functools def log(func): @functools.wraps(func) def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) #注意这里返回的只是一个函数名,并没有传入参数 return wrapper @log #注意这里的也应该是一个函数名,如果看到传入某个参数的函数,那这个函数的返回值是一个函数 def ff(): print('fun is running……') ff() #只有编写函数之前加上@log,调用这个函数的时候才会直接调用log(ff()) import functools #针对带参数的decorator def log(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) #这里的格式,牢记牢记牢记,别出错了 return func(*args, **kw) return wrapper @log('rain:') def func(): print('i love rain')