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

理解Python的装饰器

2014-03-21 15:36 537 查看
看Flask文档时候看到关于cache的装饰器,有这么一段代码:

def cached(timeout=5 * 60, key=’view/%s’):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
rv = cache.get(cache_key)
if rv is not None:
return rv
rv = f(*args, **kwargs)
cache.set(cache_key, rv, timeout=timeout)
return rv
return decorated_function
return decorator


之前也略懂装饰器,但是仔细一看发现了区别。

一般的装饰器代码是这样的:

def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for(’login’, next=request.url))
return f(*args, **kwargs)
return decorated_function


看出区别了吗?

第一个里面有两层def,第二个只有一层!

我的好奇心一下就上来了,非要把这个东西搞明白不可。

研究了一会总算研究明白了,下面就开始讲解吧。

首先理解一般的装饰器到底是怎么工作的:

def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for(’login’, next=request.url))
return f(*args, **kwargs)
return decorated_function

@login_required
def test():
print "haha"


我们用login_required装饰了test函数,那么实际上执行的语句可以理解成这样:

test = login_required(test)


也就是说,现在test变成了login_required(test)的执行结果,也就是变成了decorated_function函数。

所以我们每次执行test的时候,其实执行的就是decorated_function,而原来的test函数就变成了decorated_function中的f函数。实现了装饰功能。

下面我们看看两层嵌套的装饰器到底是怎么工作的:

def cached(timeout=5 * 60, key=’view/%s’):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
rv = cache.get(cache_key)
if rv is not None:
return rv
rv = f(*args, **kwargs)
cache.set(cache_key, rv, timeout=timeout)
return rv
return decorated_function
return decorator

@cached(100)
def test():
pass


好像没什么区别?

再仔细看看!

@cached(100)

这里多了个参数!

是的,秘密就在这个参数。

加了参数之后,装饰器的装饰过程变成了两步:

cached_temp = cached(100)
test = cached_temp(test)


Python内部肯定没有cached_temp这个变量,这是我加的。不过实际的执行过程就是这么个顺序,这下就一目了然了吧!

首先运行cached(100),这时候返回的是第一层def,也就是真正的装饰器。

然后运行cached_temp(test),这时候返回了第二层def,这步就和一般的装饰器一样了。

我们总结一下,嵌套两层def的目的就是实现“带参装饰器”,相当于可以通过参数来定制一个装饰器,然后再应用到函数上。

明白了吗?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: