为什么不能在定义之间链接Python装饰器? [英] Why can't Python decorators be chained across definitions?
问题描述
以下两个脚本为什么不等效?
Why arn't the following two scripts equivalent?
(来自另一个问题:了解Python装饰器)
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makebold
@makeitalic
def hello():
return "hello world"
print hello() ## returns <b><i>hello world</i></b>
并带有装饰性装饰器:
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
@makebold
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makeitalic
def hello():
return "hello world"
print hello() ## TypeError: wrapped() takes no arguments (1 given)
我为什么想知道?我已经编写了一个 retry
装饰器来捕获MySQLdb异常-如果该异常是短暂的(例如Timeout),它将在睡眠一小会后重新调用该函数。
Why do I want to know? I've written a retry
decorator to catch MySQLdb exceptions - if the exception is transient (e.g. Timeout) it will re-call the function after sleeping a bit.
我还有一个 modifys_db
装饰器,用于处理一些与缓存有关的内务处理。 modify_db
用 retry
装饰,所以我假设所有用 modify_db $装饰的函数c $ c>也会隐式重试。我在哪里出错了?
I've also got a modifies_db
decorator which takes care of some cache-related housekeeping. modifies_db
is decorated with retry
, so I assumed that all functions decorated with modifies_db
would also retry implicitly. Where did I go wrong?
推荐答案
第二个示例的问题是
@makebold
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
试图装饰 makeitalic
,装饰器,而不是包装的
,它返回的函数。
is trying to decorate makeitalic
, the decorator, and not wrapped
, the function it returns.
您可以按照我的想法做您打算使用这样的东西:
You can do what I think you intend with something like this:
def makeitalic(fn):
@makebold
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
此处 makeitalic
使用 makebold
装饰包裹的
。
这篇关于为什么不能在定义之间链接Python装饰器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!