Delving into Python Decorators: Part 1

Ashwin Nair
Analytics Vidhya
Published in
3 min readJul 20, 2020
Python Decorators: Part 1

This is part one of the four-part series on decorators in Python.

Decorators are a powerful Python feature for multiple reasons. They allow us to extend the behavior of a Callable[1] without permanently modifying them. They improve readability, maintainability, and thereby productivity. Aside from that, decorators have more practical uses in the modern programmer’s toolbox. You can use them to log functions, which can be helpful when debugging, or to time functions, to see how long it takes a function to execute. These are also examples that will be touched upon in more detail in the next few articles in the this series.

Decorators can only be used on callables. Callables in Python include Classes, Functions, and Methods [2]. Taking functions as an example, decorators allow us to execute code before and or after the decorated function without directly altering the function itself.

As mentioned earlier, It’s important to note that you can use a function as a decorator as is since it is a callable. However, you must make a class callable to use a decorator, as they are not by default [3]. This can be done by adding a __call__() method in the class.

Below is an example of a function being decorated.

An example of simple function being decorated.

The above code can also be written as:

test_function = test_decorator(test_function) or modified_function = test_decorator(test_function).

In the first instance, the original function is modified. The second case, however preserves the test_function as is. This way, one can use test_function() when you need to, and use modified_function() when appropriate [4].

Now, let’s take a look at a more concrete example:

An example of a decorator function and a function being decorated.

While this may seem more complicated than the last example, it really isn’t. One possible question could be “Why is the innerFunc() being used?". The innerFunc() is being used to wrap the test_function(), by calling it in between the print statements. See the output:

Output for the earlier function.

As you can see, the decorator is working quite well. Now you could argue that it would take less work to just input the print statements into the test_function(), but in the long run, you can reuse the test_decorator with more ease, and organization. For example:

An example showing the added utility that decorator functions provide.

Finally, we see the versatility of decorators. Instead of adding more print statements, we simply added @test_decorator to the beginning of the function, which produced the following output:

Output for the earlier function.

Note: The empty print statement was added to separate the two functions output.

In conclusion, decorators can be used to vastly improve the organization, readability and efficiency of your code. So, next time you see the opportunity to utilize a decorator instead of putting repetitive lines in your function, give it a try. You might just like the feeling of ease it brings. If you liked this article, be on the lookout for part 2 and more in the series. In the next article, we will be covering logging decorators and how to create one. Thanks for reading, and stay tuned for more!

--

--

Ashwin Nair
Analytics Vidhya

Pursuing my bachelors in Computer Science, while learning Natural Language Processing with SpaCy and Python.