Harsh Shah
Python decorators turn out to be an effective tool, if you properly use them. But do we even know how to use them. If not, then you've come to the right place. So without further ado, let's get started.
To follow along you, you need to know the concept of functions as a variable. If you think you know it, feel free to skip to next heading. If not, I got you covered.
Consider the following code:
def func1(temp):
print("Inside func1", temp)
def usingFunc(myFunc, value):
myFunc(value)
usingFunc(func1, "This really works!")
# Output => "Inside func1, This really works!"
As we all heard, that anything in a program gradually boils down to memory locations and the name given to access that location is called variable. So, if it is the truth that means a function is also just a variable unless you call it. Hence, we can pass functions as variables. Now here in the code, we see that we pass the func1 in the function usingFunc . Hope this helps.
Now if the function is a variable, it also follows it rules, right? You would say "Obviously". And yes you are correct 👏. So now we can also return functions without calling and define a function inside a function. And since the function is a variable, it also has a scope, same as that of a variable.
def outerFunc(key):
def innerFunc(value):
print(key, value)
return innerFunc
inner = outerFunc("Secret Key")
inner("Value")
Find the answer to this. And if you do, leave a comment below and give yourself a good pat.
Now here comes the core of the article.
Now the decorator is basically a way to increase the functionality of a function, by wrapping it in another function but in a syntactic manner. Pretty exciting, right?
Let's first see how to create a decorator.
def prettify(func):
def inner():
print("Decorator called...")
func()
return inner
In the code segment above, we have a function inner inside the prettify function. Also the prettify function recieves an argument, i.e., func which is the function to which we want to add additional functionality, or in simpler terms, we want to decorate the func. The prettify function also returns another function reference inner that adds the extra functionality and then calls our functiion func.
As defined in the previous segment, we can now use the prettify function as decorator. Here is the code to do that
def func():
print("In a function")
decorated_func = prettify(func)
decorated_func()
# Output:
# Decorator called...
# In a function
In the above code, we see that I created a function named func1 and passed it to prettify function as an argument. Now, the prettify function returns a function reference, that has the extra functionality along with the core functionality of func1 . Now we call the function that prettify returned. After calling, the output of the program is given in the code.
Now the essentials of the decorators are over, but why not a bonus? The above code is fine and it works. But is it not cumbersome? If you think it is, welcome to the club. Even the python developers thought so, hence they came up with @ <>{obj.text}> symbol. Here's how it works.
@prettify
def func():
print("Another func...")
Now this is the same thing as above, the only difference is the writing style. In the above function, we called prettify and passed the function func. Here the python interpreter understands that the prettify function is a decorator because of the @ symbol, and hence, passes the function func by itself. Now we can simply call the function func and it works like a charm! 🌟
The above examples were simple, not with any parameters, but let's say I want to prettify this function
def add(x, y):
print(x+y)
To do so, we need to modify our prettify function to accomodate so.
def prettify(func):
def inner(a, b):
print("Decorator called...")
func(a, b)
return inner
If you pay attention, you can see that I added two arguments to the inner function to accomodate the things we need to pass to the add function.
def prettify(func):
def inner(a, b):
print("Decorator called...")
func(a, b)
return inner
@prettify
def add(x, y):
print(x+y)
add(19, 21)
I write articles on web dev and more specifically on react and next js.