Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

Python Decorators

Python decorators are a powerful tool for modifying the behavior of functions or classes in a concise and flexible way. In this article, we’ll explore what decorators are, how to use them, and some practical examples.

What are decorators?

In Python, functions are first-class objects, which means that they can be passed around and manipulated just like any other data type. Decorators take advantage of this feature by allowing you to modify the behavior of a function without changing its source code.

A decorator is a higher-order function that takes a function as input and returns a new function as output. The new function has the same name as the original function, but with modified behavior. This is achieved by wrapping the original function in another function, which can perform some additional operations before or after calling the original function.

Here’s a simple example of a decorator:

In this example, we define a decorator function called my_decorator that takes a function func as input. Inside the decorator, we define a new function wrapper that performs some additional operations before and after calling func. Finally, we return wrapper the new function that replaces the original my_function.

To apply the decorator to my_function, we use the @my_decorator syntax, which is a shorthand for calling my_decorator with my_function as its argument and assigning the result to my_function.

When we call my_function(), the decorator is automatically applied, so we see the following output:

Decorating functions with arguments

So far, our decorator only works for functions with no arguments. However, it’s also possible to write decorators that work for functions with arbitrary arguments. To do this, we can use the *args and **kwargs syntax to capture the arguments passed to the original function and pass them to the wrapper function.

Here’s an example:

In this example, we modify our decorator to take *args and **kwargs as input, which allows us to capture any number of arguments and keyword arguments. Inside the decorator, we call func(*args, **kwargs) to pass the arguments to the original function and capture its return value.

When we call my_function(2, 3), the decorator is applied as before, and we see the following output:

Chaining multiple decorators

It’s also possible to apply multiple decorators to the same function by chaining them together with the @ syntax. When we use multiple decorators, they are applied from the top down, so the last decorator in the chain is applied first.

Here’s an example of chaining two decorators: