您的位置:首页 > 编程语言 > Python开发

python 装饰器详解

2017-09-14 16:59 232 查看

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: