What is Decorator in Python?

August 18, 2025   10 Min Read 28

A decorator in Python is a function that modifies the behavior of another function or class without changing its actual code.

  • It takes a function as input.
  • Adds some extra functionality.
  • Returns the modified function.
  • In Python, functions are first-class citizens → meaning we can pass functions as arguments, return them from other functions, and assign them to variables.
  • A decorator is just a function that takes another functions as input and returns a modified version of that function.

📌 Think of it like wrapping a gift: the original gift (function) is inside, but you add some decoration (extra logic).

Closures & Syntax — Closures (Core Concept of Decorators)

A closure is a function that remebers variables from its enclosing scope, even after the scope is finished.

🔹 Example


def outer():
	message = "Hello Akash"
	
	def inner():
		print(message)  # remembers "message"
	
	return inner

func = outer()
func()

👉 Output: Hello Akash

This "remembering" ability allows decorators to wrap logic around another function.

🔹 Example – Simple Decorator


def my_decorator(func):
	def wrapper():
		print("Before function execution")
		func()
		print("After function execution")
	return wrapper


@my_decorator
def say_hello():
	print("Hello, Akash")


say_hello()

Output:


Before function execution
Hello, Akash!
After function execution

Here:

  • @my_decorator is syntactic sugar for say_hello = my_decorator(say_hello).
  • It wraps say_hello with extra logic.

With Parameters & Real Use Cases

🔹 Example – Decorator with Arguments


def log_arguments(func):
	def wrapper(*args, **kwargs):
		print(f"Arguments were: {args} {kwargs}")
		return func(*args, **kwargs)
	return wrapper


@log_arguments
def add(a, b):
	return a + b


print(add(5, 10))

Output:


Arguments were: (5, 10), {}
15

Another Example: Decorators with Arguments


def repeat(n):
	def decorator(func):
		def wrapper(*args, **kwargs):
			for _, in range(n):
				func(*args, **kwargs)
		return wrapper
	return decorator


@repeat(3)
def say_hello(name):
	print(f"Hello {name}")


say_hello("Akash")

👉 Output:


Hello Akash
Hello Akash
Hello Akash

Built-in Decorators in Python

  • @staticmethod
  • @classmethod
  • @property
  • @functools.lru_cache for (caching function results)
  • @functools.wraps (to preserve metadata of decorator function)

Example:


from functools import lru_cache


@lru_cache(maxsize=100)
def fib(n):
	if n < 2:
		return n
	return fib(n - 1) + fib(n - 2)


print(fib(30))

👉 Efficient Fibonacci due to caching.

🔹 Real-life Use Cases

  • Authentication in Django (@login_required)
  • Caching results (@lru_cache from functools)
  • Logging & Debugging
  • Rate limiting / permission checks

1. Django Authentication


from django.contrib.auth.decorators import login_required
from django.http import HttpResponse


@login_required
def dashboard(request):
	return HttpResponse("Welcome to your dashboard")

2. Logging


def log(func):
	def wrapper(*args, **kwargs):
		print(f"Calling {func.__name__} with {args}, {kwargs}")
		return func(*args, **kwargs)
	return wrapper

3, Timing Functions


import time


def timing(func):
	def wrapper(*args, **kwargs):
		start = time.time()
		result = func(*args, **kwargs)
		end = time.time()
		print(f"{func.__name__} took {end - start:.4f} sec")
		return result
	return wrapper


@timing
def slow_function():
	time.sleep(2)


slow_function()

 

Interview-Ready Answer

In Python, a decorator is a higher-order function that allows us to modify or enhance the behavior of another function or method without changing its code. Internally, it uses closures and higher-order functions.

For example, Django uses decorators like @login_required for authentication. Python also provides built-in decorators like @staticmethod, @classmethod, and @property. Decorators are heavily used for logging, caching, authentication, performance measurement, and reusable cross-cutting concerns.

Leave a Reply