Reputation: 23
I have a decorator that has to add HTML tags to a string. The decorator works fine if it has to wrap a fixed string.
def tagger(fn):
def wrapper(*x):
return "<strong>" + fn() + "</strong>"
return wrapper
@tagger
def foo():
return 'Hello'
print(foo())
But if I remove the fixed string and add a parameter to the function foo()
, the decorator doesn't work.
def tagger(fn):
def wrapper(*x):
return "<strong>" + fn() + "</strong>"
return wrapper
@tagger
def foo(x):
return str(x)
print(foo('Hello'))
What am I doing wrong?
Upvotes: 1
Views: 305
Reputation: 1121494
You never pass on the parameter. The expression fn()
in the wrapper is a call to the original, decorated function, but you don't pass the arguments on.
Your decorator wrapper accepts arbitrary positional arguments as *x
, pass those into the fn()
call:
def tagger(fn):
def wrapper(*x):
return "<strong>" + fn(*x) + "</strong>"
return wrapper
For completion sake, you also want to pass on keyword arguments, and use the more common args
and kwargs
names for these variables:
def tagger(fn):
def wrapper(*args, **kwargs):
return "<strong>" + fn(*args, **kwargs) + "</strong>"
return wrapper
Now the decorator can be used on functions that take keyword arguments as well.
Upvotes: 2
Reputation: 5279
You missed forwarding any *args into the fn()
call.
def tagger(fn):
def wrapper(*x):
return "<strong>" + fn(*x) + "</strong>" # <-- This will call foo(*x)
return wrapper
@tagger
def foo(x):
return str(x)
print(foo('Hello'))
Upvotes: 3