1. 最简单的装饰器
def decorator(fun):
print 'decorator befor warpper'
def wrapper():
print 'wrapper begin'
fun()
print 'wrapper end'
return wrapper
@decorator
def decorated_do_something():
print 'decorated do something'
print decorated_do_something
print '*******************'
print decorated_do_something()
运行结果:
decorator befor warpper
<function wrapper at 0x0000000002BEE828>
*******************
wrapper begin
decorated do something
wrapper end
None
所以:
1. decorated_do_something相当于decorator(decorated_do_something),所以返回是wrapper 方法。
2. decorated_do_something()相当于decorator(decorated_do_something)(), 即wrapper()
测试查看decorated_do_something的函数名:
def decorator(fun):
print 'decorator befor warpper'
def wrapper():
print 'wrapper begin'
fun()
print 'wrapper end'
return wrapper
@decorator
def decorated_do_something():
print 'decorated do something'
print decorated_do_something.__name__
运行结果如下:
decorator befor warpper
wrapper
2. 目标函数带固定参数的装饰器
def decorator(fun):
print 'decorator befor warpper'
def wrapper(arg):
print 'wrapper begin'
print 'arg: '+arg
fun(arg)
print 'wrapper end'
return wrapper
@decorator
def decorated_do_something(arg):
print 'decorated do something'
print 'arg: '+arg
def do_something(arg):
print 'do something'
print 'arg: '+arg
decorated_do_something('decorated arg')
运行结果如下:
decorator befor warpper
wrapper begin
arg: decorated arg
decorated do something
arg: decorated arg
wrapper end
decorated_do_something(‘decorated arg’)相当于decorator(decorated_do_something)(‘decorated arg’)
3. 目标函数带不固定参数的装饰器
ddef decorator(fun):
print 'decorator befor warpper'
def wrapper(*args, **kwargs):
print 'wrapper begin'
print 'args: '+ str(args)+"; kwargs: "+ str(kwargs)
fun(*args, **kwargs)
print 'wrapper end'
return wrapper
@decorator
def decorated_do_something1(arg):
print 'decorated do something'
print 'arg: '+arg
print 'decorated_do_something1 end'
@decorator
def decorated_do_something2(*args, **kwargs):
print 'do something'
print 'args: '+ str(args)+"; kwargs: "+ str(kwargs)
print 'decorated_do_something2 end'
decorated_do_something1('only one arg')
print '***************'
decorated_do_something2('arg1','arg2', arg3='arg3',arg4='arg4')
运行结果如下:
decorator befor warpper
decorator befor warpper
wrapper begin
args: ('only one arg',); kwargs: {}
decorated do something
arg: only one arg
decorated_do_something1 end
wrapper end
***************
wrapper begin
args: ('arg1', 'arg2'); kwargs: {'arg3': 'arg3', 'arg4': 'arg4'}
do something
args: ('arg1', 'arg2'); kwargs: {'arg3': 'arg3', 'arg4': 'arg4'}
decorated_do_something2 end
wrapper end
4. 带参数的装饰器
def decorator(arg):
print 'decorator before _decorator, decorator arg: '+arg
def _decorator(fun):
print 'decorator befor warpper'
def wrapper(*args, **kwargs):
print 'wrapper begin'
print 'args: '+ str(args)+"; kwargs: "+ str(kwargs)
fun(*args, **kwargs)
print 'wrapper end'
return wrapper
return _decorator
@decorator('2')
def decorated_do_something(arg):
print 'decorated do something started'
print 'arg: '+arg
print 'decorated_do_something end'
print decorated_do_something.__name__
decorated_do_something("decorated_do_something's arg")
运行结果如下:
decorator before _decorator, decorator arg: 2
decorator befor warpper
wrapper
wrapper begin
args: ("decorated_do_something's arg",); kwargs: {}
decorated do something started
arg: decorated_do_something's arg
decorated_do_something end
wrapper end
5. 被装饰器装饰过的函数的函数名
def decorator(fun):
def wrapper(*args, **kwargs):
fun(*args, **kwargs)
return wrapper
@decorator
def decorated_do_something():
print 'decorated do something started'
print decorated_do_something.__name__
运行结果:
wrapper
可以看出, decorated_do_something的函数名变成了wrapper,这不是我们想要的。 python的unctools.wraps提供了解决方法
import functools
def decorator(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
fun(*args, **kwargs)
return wrapper
@decorator
def decorated_do_something():
print 'decorated do something started'
print decorated_do_something.__name__
运行结果:
decorated_do_something
6. 装饰器类
需求:让函数只能运行指定次数
class decorator():
def __init__(self, max):
self.max=max
self.count=0
def __call__(self,fun):
self.fun=fun
return self.call_fun
def call_fun(self, *args, **kw):
self.count +=1
if(self.count>self.max):
print "%s run more than %d times" %(self.fun.__name__, self.max)
else:
self.fun(*args, **kw)
@decorator(2)
def decorated_do_something():
print 'decorated_do_something running'
@decorator(3)
def decorated_do_something1():
print 'decorated_do_something1 running'
for i in xrange(4):
decorated_do_something()
decorated_do_something1()
运行结果:
decorated_do_something running
decorated_do_something1 running
decorated_do_something running
decorated_do_something1 running
decorated_do_something run more than 2 times
decorated_do_something1 running
decorated_do_something run more than 2 times
decorated_do_something1 run more than 3 times
decorated_do_something相当于 decorator.init(args)(fun)