Decorators — Python

I had an article on decorators written a year ago and now when I go over it I think I could have done a lot better job especially in the second half. So compensating for it here. For a pre-requisite, you should understand how closure works.
In this article, we’ll understand what decorators are with examples of simple, stacked, and parameterized decorators. We also have dynamic decorators as a bonus.
Let’s see a simple example:
On running the file we get:
9*2= 18
prod called 1 times.
Now let’s dissect the counter
function:

As shown by the dashed lines, counter
function encloses inner
function using its local variable fn
and count
.
The way we have called the counter
function is by passing prod
function to it. The counter
function returns inner
function which gets invoked by passing parameters to it and is used by the prod
function passed during invocation of the counter
function.
Line number 13 and 14 of the code does these invocations:
inner = counter(prod)
inner(9,2)
We can do the same invocation using @<decorator-name>
symbol. Hence, we don’t have to do line 13 way of invoking nested functions.
When a function is decorated, you can think of it as whole function gets passed to the decorator and gets used in inner function of the decorator.
Let’s look into stack decorators with an example:
On running the file we get:
running dash function...
running upper function...
C-R-O-W-N- -O-F- -W-I-L-D- -O-L-I-V-E
As you see in the output, if there are stacked decorators, the decorators in the outside takes decorators beneath it as parameter being passed to it. It recursively reaches to the innermost decorator and comes up completing each inner function calls.
So here upper(fn)
‘s inner
method will be executed first then dash(fn)
’s inner
method.
Here is a digram for the explanation:

Let’s make a small modification so that we can call this stacked decorator 5 times.
On running the file we get:
C-R-O-W-N- -O-F- -W-I-L-D- -O-L-I-V-E
C-R-O-W-N- -O-F- -W-I-L-D- -O-L-I-V-E
C-R-O-W-N- -O-F- -W-I-L-D- -O-L-I-V-E
C-R-O-W-N- -O-F- -W-I-L-D- -O-L-I-V-E
C-R-O-W-N- -O-F- -W-I-L-D- -O-L-I-V-E
What we did was define parametrized outer decorator rep
that takes value times
and encloses dash
decorator. The dash
decorator’s inner method uses the rep
's parameter for iteration.
What we are doing in decorators is basically decorating functions!
That is all for decorators. Hope that was helpful and helped with your understanding. If you have any clarification do comment.
Congratulations on the completions! 🎈 My next article will be on tuples and namedtuples. See you then.
Bonus: This maybe a little intimidating dynamic stacked decorator for mapping middle layer node to lower layer device/s. Have a look, play-around and should be a good temperature test on handling decorators’s concept. Pre-requisites: Closure, lambda function
On running the file, we get:
lower-node-1 is mapped to ['router-x-1', 'router-x-2']
lower-node-2 is mapped to ['firewall-x-1']
lower-node-3 is mapped to ['firewall-next-gen-x-1', 'vm-2.2']
Not a valid mapping