基础用法:廖雪峰python教程
# log为装饰器decorator def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper @log def now(): print('2015-3-25')
运行:now() 相当于执行 now = log(now),可以发现now的__name__属性变为wrapper,使用functools工具确保被装饰函数的name属性不变
import functools def log(func): @functools.wraps(func) def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper
若装饰器带参数,需要编写一个返回decorator的高阶函数
import functools 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 return decorator @log('execute') def now(): print('2015-3-25') ''' 执行结果: >>> now() execute now(): 2015-3-25 等价于now = log('execute')(now) '''
拓展到类装饰器(如下解释):参考
- 装饰器无参数
class tracer: def __init__(self,func): self.calls = 0 self.func = func print("dd", func.__name__) def __call__(self,*args): self.calls += 1 print('call %s to %s' %(self.calls, self.func.__name__)) self.func(*args) @tracer def spam(a, b, c): print(a + b + c) # 写完运行结果有dd spam @tracer def spam2(a, b, c): print(a - b - c) # 写完运行结果有dd spam2 '''相当于实例化了'''
- 装饰器有参数
class tracer: def __init__(self, *args): self.calls = 0 self.args = args def __call__(self, func): self.func = func def realfunc(*args): self.calls += 1 print('call %s to %s' %(self.calls, self.func.__name__)) self.func(*args) return realfunc @tracer("xxxx") def spam(a, b, c): print(a + b + c) # 相当于是把待装饰的函数当参数传给了call函数
相当于实例化类之后,再装饰
年岁有加并非垂老
理想丢弃方堕暮年