Last Updated : 11 Jul, 2025
In Python, decorators are a powerful and flexible way to modify or extend the behavior of functions or methods, without changing their actual code. A decorator is essentially a function that takes another function as an argument and returns a new function with enhanced functionality.
Decorators are often used in scenarios such as logging, authentication and memorization, allowing us to add additional functionality to existing functions or methods in a clean, reusable way.
Decorator Example: Python
# A simple decorator function
def decorator(func):
def wrapper():
print("Before calling the function.")
func()
print("After calling the function.")
return wrapper
# Applying the decorator to a function
@decorator
def greet():
print("Hello, World!")
greet()
Before calling the function. Hello, World! After calling the function.
Explanation:
Let's explore decorators in detail:
Syntax of Decorator ParametersExplanation of Parametersdef decorator_name(func):
def wrapper(*args, **kwargs):
# Add functionality before the original function call
result = func(*args, **kwargs)
# Add functionality after the original function call
return result
return wrapper@decorator_name
def function_to_decorate():
# Original function code
pass
1. decorator_name(func):
2. wrapper(*args, **kwargs):
3. @decorator_name:
In Python, higher-order functions are functions that take one or more functions as arguments, return a function as a result or do both. Essentially, a higher-order function is a function that operates on other functions. This is a powerful concept in functional programming and is a key component in understanding how decorators work.
Key Properties of Higher-Order Functions:Example of a Higher-Order Function:
Python
# A higher-order function that takes another function as an argument
def fun(f, x):
return f(x)
# A simple function to pass
def square(x):
return x * x
# Using apply_function to apply the square function
res = fun(square, 5)
print(res)
In this example, first function fun is a higher-order function because it takes another function f as an argument and applies it to the value x.
Role in Decorators:Decorators in Python are a type of higher-order function because they take a function as input, modify it, and return a new function that extends or changes its behavior. Understanding higher-order functions is essential for working with decorators since decorators are essentially functions that return other functions.
Functions as First-Class ObjectsIn Python, functions are first-class objects, meaning that they can be treated like any other object, such as integers, strings, or lists. This gives functions a unique level of flexibility and allows them to be passed around and manipulated in ways that are not possible in many other programming languages.
What Does It Mean for Functions to Be First-Class Objects?
# Assigning a function to a variable
def greet(n):
return f"Hello, {n}!"
say_hi = greet # Assign the greet function to say_hi
print(say_hi("Alice")) # Output: Hello, Alice!
# Passing a function as an argument
def apply(f, v):
return f(v)
res = apply(say_hi, "Bob")
print(res) # Output: Hello, Bob!
# Returning a function from another function
def make_mult(f):
def mult(x):
return x * f
return mult
dbl = make_mult(2)
print(dbl(5)) # Output: 10
Hello, Alice! Hello, Bob! 10
Explanation:
The most common type of decorator, which takes a function as input and returns a new function. The example above demonstrates this type.
Python
def simple_decorator(func):
def wrapper():
print("Before calling the function.")
func()
print("After calling the function.")
return wrapper
@simple_decorator
def greet():
print("Hello, World!")
greet()
Before calling the function. Hello, World! After calling the function.
Explanation:
Used to decorate methods within a class. They often handle special cases, such as the self
argument for instance methods.
def method_decorator(func):
def wrapper(self, *args, **kwargs):
print("Before method execution")
res = func(self, *args, **kwargs)
print("After method execution")
return res
return wrapper
class MyClass:
@method_decorator
def say_hello(self):
print("Hello!")
obj = MyClass()
obj.say_hello()
Before method execution Hello! After method execution
Explanation:
Class decorators are used to modify or enhance the behavior of a class. Like function decorators, class decorators are applied to the class definition. They work by taking the class as an argument and returning a modified version of the class.
Example:
Python
def fun(cls):
cls.class_name = cls.__name__
return cls
@fun
class Person:
pass
print(Person.class_name)
Explanation:
Python provides several built-in decorators that are commonly used in class definitions. These decorators modify the behavior of methods and attributes in a class, making it easier to manage and use them effectively. The most frequently used built-in decorators are @staticmethod
, @classmethod
, and @property
.
The @staticmethod
decorator is used to define a method that doesn't operate on an instance of the class (i.e., it doesn't use self
). Static methods are called on the class itself, not on an instance of the class.
Example:
Python
class MathOperations:
@staticmethod
def add(x, y):
return x + y
# Using the static method
res = MathOperations.add(5, 3)
print(res)
Explanation:
The @classmethod decorator is used to define a method that operates on the class itself (i.e., it uses cls). Class methods can access and modify class state that applies across all instances of the class.
Example:
Python
class Employee:
raise_amount = 1.05
def __init__(self, name, salary):
self.name = name
self.salary = salary
@classmethod
def set_raise_amount(cls, amount):
cls.raise_amount = amount
# Using the class method
Employee.set_raise_amount(1.10)
print(Employee.raise_amount)
Explanation:
The @property decorator is used to define a method as a property, which allows you to access it like an attribute. This is useful for encapsulating the implementation of a method while still providing a simple interface.
Example:
Python
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value >= 0:
self._radius = value
else:
raise ValueError("Radius cannot be negative")
@property
def area(self):
return 3.14159 * (self._radius ** 2)
# Using the property
c = Circle(5)
print(c.radius)
print(c.area)
c.radius = 10
print(c.area)
5 78.53975 314.159
Explanation:
In simpler terms chaining decorators means decorating a function with multiple decorators.
Example:
Python
# code for testing decorator chaining
def decor1(func):
def inner():
x = func()
return x * x
return inner
def decor(func):
def inner():
x = func()
return 2 * x
return inner
@decor1
@decor
def num():
return 10
@decor
@decor1
def num2():
return 10
print(num())
print(num2())
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4