codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🐍

Python Programming

39 / 68 topics
36List Comprehensions37Python Iterators38Python Generators39Python Decorators40Python Modules, Packages & PIP41Python Main Function (__name__ == '__main__')42Python Dates and Time43Python Regular Expressions44Python JSON
Tutorials/Python Programming/Python Decorators
🐍Python Programming

Python Decorators

Updated 2026-05-15
30 min read

Python Decorators

Decorators are a powerful feature in Python that allow you to modify the behavior of functions or methods. They provide a flexible way to extend and enhance your code without permanently modifying it. In this tutorial, we'll explore how to use decorators, including function decorators with the @ syntax, using functools.wraps, decorators with arguments, class decorators, and chaining decorators.

Introduction

Decorators are essentially functions that take another function as an argument and extend its behavior without explicitly modifying it. They are a great tool for adding functionality to existing code in a clean and reusable way. In Python, decorators can be applied using the @ syntax, which makes them easy to read and apply.

Function Decorators

A decorator is a function that takes another function as an argument and returns a new function. The simplest form of a decorator uses the @ syntax to wrap a function.

Basic Example

Let's start with a basic example where we create a simple decorator that prints a message before calling the original function.

basic_decorator.py
1def my_decorator(func):
2 def wrapper():
3 print("Something is happening before the function is called.")
4 func()
5 print("Something is happening after the function is called.")
6 return wrapper
7
8@my_decorator
9def say_hello():
10 print("Hello!")
11
12say_hello()
Output
Something is happening before the function is called.
Hello!
Something is happening after the function is called.

In this example, my_decorator is a decorator that takes a function func as an argument. Inside my_decorator, we define a nested function wrapper that adds some behavior before and after calling func. The @my_decorator syntax is syntactic sugar for say_hello = my_decorator(say_hello).

Using functools.wraps

When you create a decorator, the metadata of the original function (like its name and docstring) is lost. To preserve this information, you can use the functools.wraps decorator.

wraps_example.py
1import functools
2
3def my_decorator(func):
4 @functools.wraps(func)
5 def wrapper():
6 print("Something is happening before the function is called.")
7 func()
8 print("Something is happening after the function is called.")
9 return wrapper
10
11@my_decorator
12def say_hello():
13 """Prints a greeting."""
14 print("Hello!")
15
16print(say_hello.__name__) # Output: say_hello
17print(say_hello.__doc__) # Output: Prints a greeting.
Output
say_hello
Prints a greeting.

Using functools.wraps ensures that the original function's metadata is preserved, which is important for debugging and documentation.

Decorators with Arguments

Decorators can also take arguments. To achieve this, you need to define an outer function that takes the decorator arguments and returns a decorator.

Example with Arguments

Here's an example of a decorator that measures the execution time of a function:

decorator_with_args.py
1import time
2import functools
3
4def timer(func):
5 @functools.wraps(func)
6 def wrapper(*args, **kwargs):
7 start_time = time.time()
8 result = func(*args, **kwargs)
9 end_time = time.time()
10 print(f"{func.__name__} executed in {end_time - start_time:.4f} seconds")
11 return result
12 return wrapper
13
14@timer
15def compute_sum(n):
16 """Computes the sum of numbers from 1 to n."""
17 return sum(range(1, n + 1))
18
19print(compute_sum(1000000))
Output
compute_sum executed in 0.0256 seconds
499999500000

In this example, the timer decorator takes a function func as an argument and returns a new function wrapper. The wrapper function measures the time taken to execute func and prints it.

Class Decorators

Decorators can also be applied to classes. A class decorator is a function that takes a class as an argument and returns a modified version of that class.

Basic Example

Let's create a simple class decorator that adds an attribute to a class.

class_decorator.py
1def add_attribute(cls):
2 cls.new_attribute = "Added by decorator"
3 return cls
4
5@add_attribute
6class MyClass:
7 pass
8
9print(MyClass.new_attribute) # Output: Added by decorator
Output
Added by decorator

In this example, add_attribute is a class decorator that adds an attribute new_attribute to the class it decorates.

Chaining Decorators

Decorators can be chained together, meaning you can apply multiple decorators to a single function. The order of application matters, as each decorator modifies the behavior of the previous one.

Example of Chaining Decorators

Let's create two simple decorators and chain them together.

chaining_decorators.py
1def first_decorator(func):
2 @functools.wraps(func)
3 def wrapper():
4 print("First decorator")
5 func()
6 return wrapper
7
8def second_decorator(func):
9 @functools.wraps(func)
10 def wrapper():
11 print("Second decorator")
12 func()
13 return wrapper
14
15@first_decorator
16@second_decorator
17def greet():
18 print("Hello!")
19
20greet()
Output
First decorator
Second decorator
Hello!

In this example, the greet function is decorated with both first_decorator and second_decorator. The order of application is from bottom to top, so second_decorator is applied first, followed by first_decorator.

Practical Example

Let's put all these concepts together in a practical example. We'll create a decorator that logs the execution time of a function and another that adds an attribute to a class.

practical_example.py
1import time
2import functools
3
4def timer(func):
5 @functools.wraps(func)
6 def wrapper(*args, **kwargs):
7 start_time = time.time()
8 result = func(*args, **kwargs)
9 end_time = time.time()
10 print(f"{func.__name__} executed in {end_time - start_time:.4f} seconds")
11 return result
12 return wrapper
13
14def add_attribute(cls):
15 cls.new_attribute = "Added by decorator"
16 return cls
17
18@timer
19def compute_sum(n):
20 """Computes the sum of numbers from 1 to n."""
21 return sum(range(1, n + 1))
22
23@add_attribute
24class MyClass:
25 pass
26
27print(compute_sum(1000000))
28print(MyClass.new_attribute)
Output
compute_sum executed in 0.0256 seconds
499999500000
Added by decorator

In this example, we use the timer decorator to measure the execution time of the compute_sum function and the add_attribute class decorator to add an attribute to the MyClass class.

Summary

ConceptDescription
Function DecoratorsFunctions that modify other functions without permanently changing them.
@ SyntaxSyntactic sugar for applying decorators.
functools.wrapsPreserves the metadata of the original function.
Decorators with ArgsDecorators that take arguments and return a decorator.
Class DecoratorsFunctions that modify classes by adding attributes or methods.
Chaining DecoratorsApplying multiple decorators to a single function in a specific order.

What's Next?

Now that you have a solid understanding of decorators, the next step is to learn about Python modules, packages, and PIP. Modules allow you to organize your code into reusable components, while packages help manage dependencies and distribute your code. PIP is the package installer for Python, which makes it easy to install and manage third-party libraries.

In the next tutorial, we'll explore how to create, use, and distribute Python modules and packages using PIP. Stay tuned!


PreviousPython GeneratorsNext Python Modules, Packages & PIP

Recommended Gear

Python GeneratorsPython Modules, Packages & PIP