This article will help you understand the concept of decorators in Python programming and how best to use them. We’ll cover what Python decorators are, what their syntax looks like, how to identify them in a script or framework, and how to apply them yourself.
A function decorator in Python is just a function that takes in another function as an argument, extending the decorated function’s functionality without changing its structure. A decorator wraps another function, amplifies its behavior, and returns it.
The concept of decorators in Python help keeps your code DRY. A function decorator avoids unnecessary repetition across your codebase, because some repeated bits of code can be pulled together to become function decorators. As you advance in using Python for development, decorators can help with analytics and logging. They’re also vital for setting up validation and runtime checks.
As we proceed, I’ll assume you have a basic understanding of Python functions and programming and you have at least Python 3.8 installed on your device.
In Python, functions are first-class objects, meaning they can receive arguments or be passed as arguments. To fully grasps the concept of decorators, there are a few things you need to understand.
Always remember that everything is an object in Python. In the same way you assign values to a variable, a function can also be assigned to a variable where necessary. This is important as you learn about decorators.
An inner function in Python can be returned from the outer function. This is part of the functional programming concepts you’ll come across.
A function that receives a function argument is known as a higher order function.
The above-listed points are important to keep in mind when learning to implement decorators and use them effectively in a Python program.
A simple decorator function starts with a function definition, the decorator function, and then a nested function within the outer wrapper function.
Always keep these two main points in mind when defining decorators:
This is what the most basic decorator function looks like in the code snippet below:
Looking at the code above, the outer function increase_number
— also known as the decorator — receives a function argument func
. increase_by_one
is the wrapper function where the decorated get_number
function is found. The decorator is assigned to another variable. This is what a decorator syntax looks like when using Python decorators. However, there’s a much easier way to represent decorators.
A simple decorator function is easily identified when it begins with the @
prefix, coupled with the decorated function underneath. The previous example can be refactored to look like this:
The examples show that a decorator extends the functionality of its function argument.
There are cases where you may need to pass parameters to a decorator. The way around this is to pass parameters to the wrapper function, which are then passed down to the decorated function. See the following example:
Having parameters passed to the inner function or nested function makes it even more powerful and robust, as it gives more flexibility for manipulating the decorated function. Any number of arguments (*args
) or keyword arguments (**kwargs
) can be passed unto the decorated function. *args
allows the collection of all positional arguments, while the **kwargs
is for all keyword arguments needed during the function call. Let’s look at another simple example:
From the above example, *args
forms an iterable of positional arguments as a tuple, while the **kwargs
forms a dictionary of keyword arguments.
There are several options to explore when using function decorators in your Python project. Another use case would be chaining decorators (two or more) to a function. A function can be decorated with more than one decorator (multiple decorators), and this is achieved by stacking one decorator on top of the other in no particular order. You’ll have the same output no matter the order in which the multiple decorators are placed on top of each other, as seen in the following example:
A very popular way of using decorators in Python is as a time logger. This helps a programmer know the amount of time a function takes to execute as a way of measuring efficiency.
Memoization is another cool way to use decorators in Python. Results from function calls that are repeated without any change can be easily remembered when performing calculations later. You can simply memoize a function with decorators.
Built-in Python decorators like @classmethod
(class method), @staticmethod
(static method), and @property
are very popular in Python’s OOP decorator pattern.
Python decorators enforce the DRY principle of software engineering because they serve as reusable code. Think of the many Python functions you could refactor to decorators. In this article, we’ve explored different forms of decorators. There are also class decorators, although we haven’t touched on those here.
Decorators make it easier to add additional functionality to a simple function, method or class without having to alter its source code while keeping your code DRY. Try decorating functions on your own to better understand the decorator pattern.
Ini is a startup enthusiast, software engineer and technical writer. Flutter and Django are his favorite tools at the moment for building software solutions. He loves Afrobeats music.
© 2000 – 2022 SitePoint Pty. Ltd.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
