Why arn\'t the following two scripts equivalent?
(Taken from another question: Understanding Python Decorators)
def makebold(fn):
def wrapped():
The problem with the second example is that
@makebold
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
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
Here makeitalic
uses makebold
to decorate wrapped
.
The reason is because wrapped() inside of makebold doesn't accept any arguments.
When you use the decorator like that it can cause some issues, I'll post an example of how to achieve what you're wanting though, give me just a moment.
Here is a working example of what you need.
def makebold(rewrap=False):
if rewrap:
def inner(decorator):
def rewrapper(func):
def wrapped(*args, **kwargs):
return "<b>%s</b>" % decorator(func)(*args,**kwargs)
return wrapped
return rewrapper
return inner
else:
def inner(func):
def wrapped(*args, **kwargs):
return "<b>%s</b>" % func(*args, **kwargs)
return wrapped
return inner
@makebold(rewrap=True)
def makeitalic(fn):
def wrapped(*args, **kwargs):
return "<i>%s</i>" % fn(*args, **kwargs)
return wrapped
@makeitalic
def hello():
return "hello world"
@makebold()
def hello2():
return "Bob Dole"
if __name__ == "__main__":
print hello()
print hello2()
makebold
is kinda ugly, but it shows you how to write a decorator that can optionally wrap another decorator.
Here is the output from the above script:
<b><i>hello world</i></b>
<b>Bob Dole</b>
Note that makebold is the only recursive decorator. Also note the subtle difference in usage: @makebold()
vs @makeitalic
.
The problem is replacing "makeitalic" (which takes one argument) with the "wrapped"-function in "makebold" which takes zero arguments.
Use *args, **kwargs
to pass on arguments further down the chain:
def wrapped(*args, **kwargs):
return "<b>" + fn(*args, **kwargs) + "</b>"