为什么80%的码农都做不了架构师?>>>
装饰器,就是对被装饰的对象进行修改,其语法以@开头,然后是装饰器函数的名字和可选参数。然后是被装饰的对象及可选参数。格式如下:
@decorator(agrs)
def func(func_args):
...
为了更容易理解装饰器,要先了解下python的特性。python中一切都是对象,函数是对象,类是对象,类的实例也是对象,函数名和类名可以作为参数传递,函数名和类名后面加(), 表示调用函数和类实例化。
1.函数和方法装饰器
语法格式
类似如下:
@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
>>> 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)))
2.类装饰器
语法和函数装饰器类似:
>>> @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可以将装饰过的函数属性保留。