装饰器,就是对被装饰的对象进行修改,其语法以@开头,然后是装饰器函数的名字和可选参数。然后是被装饰的对象及可选参数。格式如下:
@decorator(agrs) def func(func_args): ...
为了更容易理解装饰器,要先了解下python的特性。python中一切都是对象,函数是对象,类是对象,类的实例也是对象,函数名和类名可以作为参数传递,函数名和类名后面加(), 表示调用函数和类实例化。
类似如下:
@decorator() def func(): ...
它实际上等价于:
def func(): ... func=decorator(func)
因为func=decorator(func), 所以调用func,func() = decorator(func)(), 大概原理就是这样。来看看一个完整的装饰器。
>>> def decorator(func): def wrapper(): print 'in decorator' func() return wrapper >>> @decorator def func(): print 'in func' >>> func <function wrapper at 0x01D600B0> >>> func() in decorator in func
语法格式如下:
@decorator(argA, argB, ...) def func(arg1, arg2, ...): pass
它实际上等价于:
def func(arg1, arg2, ...): pass func=decorator(argA, argB, ...)(func)
所以,func(arg1, arg2, ... ) = decorator(argA, argB, ...)(func)(arg1, arg2, ... )。看个带参数装饰器的例子,
>>> def decorator(*arg_deco): def deco(func): def wrapper(*arg_func): print 'in decorator, arg_deco:', arg_deco func(*arg_func) return wrapper return deco >>> @decorator('decorator args') def func(*arg_func): print 'in func, arg_func:', arg_func >>> func('func args') in decorator, arg_deco: ('decorator args',) in func, arg_func: ('func args',)
语法格式如下:
@A @B @C def f (): ...
上面代码实际上等价于:
def f(): ... f = A(B(C(f)))
>>> @decortor class A: pass
当实例化时,a=A(), 实际上等价于下面代码:
class A: pass A=decorator(A) a=A()
如何实现呢。
>>> def decorator(cls): class Wrapper: def __init__(self, *args): self.wrapped = cls(*args) def __getattr__(self, name): return getattr(self.wrapped, name) return Wrapper >>> @decorator class A: def __init__(self,x,y): self.attr = 'aaa' >>> a.attr 'aaa'
被装饰器装饰的方法或类,其属性发生了变化,如何保留呢。functools.wraps可以将装饰过的函数属性保留。