Parameterized decorator
- Python course
- Advanced
- Lesson 1/83
- 5 min
Learn to write parameterized decorators.
Parameterized decorator
A decorator is a callable that wraps another function and changes its behavior. A parameterized decorator takes extra arguments that configure the wrapping.
You first define an outer factory function: def repeat(n):. That function returns the real decorator; the decorator returns the wrapped function. The three-layer shape is:
def repeat(n):
def deco(fn):
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return decoUse it as @repeat(3); the 3 argument goes to the factory.
Preserving the signature with functools.wraps
A decorator hides the wrapped function's name, docstring and signature; from the outside, wrapper is what gets called. This breaks debugging and help output.
The fix is to put functools.wraps(fn) on top of wrapper. It copies the original function's metadata onto wrapper.
from functools import wraps
def repeat(n):
def deco(fn):
@wraps(fn)
def wrapper(*args):
...
return wrapper
return decoThat way help(my_fn) still shows the original docstring.
Practice Write a parameterized @repeat decorator
Write a three-layer parameterized decorator. The factory is repeat(n), the decorator is deco(fn) and the wrapper is wrapper(*args), nested. wrapper calls fn(*args) exactly n times. Preserve metadata with @wraps(fn). Decorate greet(name) with @repeat(2) so it prints the name value twice; end with a greet("Ayşe") call.
Starter code
from functools import wraps
# repeat(n) factory; define deco and wrapper nested inside
# decorate wrapper with the wraps decorator
# in the wrapper body call the original function n times
@repeat(2)
def greet(name):
print(name)
greet("Ayşe")Sample solution
from functools import wraps
def repeat(n):
def deco(fn):
@wraps(fn)
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return deco
@repeat(2)
def greet(name):
print(name)
greet("Ayşe")Expected output
Ayşe Ayşe
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 In a parameterized decorator, where does the 3 in @repeat(3) go?
- To the factory function (repeat) Correct answer
- Directly to the wrapped function
- To the wrapper function
- To the deco function
Explanation: repeat(3) calls the factory first; 3 binds to the n parameter of repeat.
2 Add the wraps decorator
from functools import wraps
def repeat(n):
def deco(fn):
@____(fn)
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return deco
from functools import wraps
def repeat(n):
def deco(fn):
@wraps(fn)
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return deco
Explanation: @wraps(fn) copies the original function's name and docstring to wrapper.
3 Match the parameterized decorator layers
| Term | Meaning |
|---|---|
repeat(n) |
Outer factory |
deco(fn) |
Real decorator |
wrapper(*args) |
Wrapping function |
@wraps(fn) |
Preserves metadata |