I’m trying to understand how to decorate decorators, and wanted to try out the following:
Let’s say I have two decorators and apply them to the function hello()
:
JavaScript
x
19
19
1
def wrap(f):
2
def wrapper():
3
return " ".join(f())
4
return wrapper
5
6
7
def upper(f):
8
def uppercase(*args, **kargs):
9
a,b = f(*args, **kargs)
10
return a.upper(), b.upper()
11
return uppercase
12
13
@wrap
14
@upper
15
def hello():
16
return "hello","world"
17
18
print(hello())
19
Then I have to start adding other decorators for other functions, but in general the @wrap
decorator will “wrap all of them”
JavaScript
1
11
11
1
def lower(f):
2
def lowercase(*args, **kargs):
3
a,b = f(*args, **kargs)
4
return a.lower(), b.lower()
5
return lowercase
6
7
@wrap
8
@lower
9
def byebye():
10
return "bye", "bye"
11
How do I write a decorator, which decorates my @lower
and @upper
decorators? See below:
JavaScript
1
8
1
@wrap
2
def lower():
3
4
5
@wrap
6
def upper():
7
8
To achieve the same result as above by only doing:
JavaScript
1
8
1
@upper
2
def hello():
3
4
5
@lower
6
def byebye():
7
8
Advertisement
Answer
Here’s a generic (and slightly convoluted) solution for decorating decorators with decorators (Yay!).
JavaScript
1
31
31
1
# A second-order decorator
2
def decdec(inner_dec):
3
def ddmain(outer_dec):
4
def decwrapper(f):
5
wrapped = inner_dec(outer_dec(f))
6
def fwrapper(*args, **kwargs):
7
return wrapped(*args, **kwargs)
8
return fwrapper
9
return decwrapper
10
return ddmain
11
12
def wrap(f):
13
def wrapper():
14
return " ".join(f())
15
return wrapper
16
17
18
# Decorate upper (a decorator) with wrap (another decorator)
19
@decdec(wrap)
20
def upper(f):
21
def uppercase(*args, **kargs):
22
a,b = f(*args, **kargs)
23
return a.upper(), b.upper()
24
return uppercase
25
26
@upper
27
def hello():
28
return "hello","world"
29
30
print(hello())
31