Decorators in Python

Decorators in Python

A decorator is a function that modifies the behavior of another function without permanently modifying it. Decorators are a powerful tool that use closure functions.

Basic Concept

A decorator:

  1. Takes a function as input
  2. Returns a modified function (or a new function)
  3. Uses the @decorator_name syntax

Simple Example

python

def simple_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@simple_decorator
def say_hello():
    print("Hello!")

# Using the decorated function
say_hello()

Output:

text

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

Equivalent Without @ Syntax

python

def say_hello():
    print("Hello!")

# Manual decoration
decorated_hello = simple_decorator(say_hello)
decorated_hello()

Decorator for Functions with Arguments

python

def smart_divide(func):
    def wrapper(a, b):
        print(f"Dividing {a} by {b}")
        if b == 0:
            print("Cannot divide by zero!")
            return
        return func(a, b)
    return wrapper

@smart_divide
def divide(a, b):
    return a / b

print(divide(10, 2))  # Output: Dividing 10 by 2 → 5.0
print(divide(10, 0))  # Output: Dividing 10 by 0 → Cannot divide by zero!

Decorator with Any Number of Arguments

python

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

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

@logger
def multiply(x, y, z=1):
    return x * y * z

add(3, 5)
multiply(2, 3, z=4)

Output:

text

Calling add with args: (3, 5), kwargs: {}
add returned: 8
Calling multiply with args: (2, 3), kwargs: {'z': 4}
multiply returned: 24

Practical Example: Timing Function Execution

python

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} executed in {end_time - start_time:.4f} seconds")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(2)
    return "Done!"

slow_function()  # Output: slow_function executed in 2.0002 seconds

Chaining Decorators

python

def bold(func):
    def wrapper():
        return "<b>" + func() + "</b>"
    return wrapper

def italic(func):
    def wrapper():
        return "<i>" + func() + "</i>"
    return wrapper

@bold
@italic
def hello():
    return "Hello World"

print(hello())  # Output: <b><i>Hello World</i></b>

Decorator with Arguments

python

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for i in range(n):
                print(f"Call {i+1}:")
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

Output:

text

Call 1:
Hello, Alice!
Call 2:
Hello, Alice!
Call 3:
Hello, Alice!

Why Use Decorators?

  • Code Reuse: Avoid repetitive code
  • Separation of Concerns: Keep business logic separate from cross-cutting concerns
  • Readability: Makes code more readable and maintainable
  • Extensibility: Easy to add/remove functionality

Decorators are widely used in web frameworks (like Flask, Django), testing, logging, and many other areas of Python programming!

Similar Posts

  • Quantifiers (Repetition)

    Quantifiers (Repetition) in Python Regular Expressions – Detailed Explanation Basic Quantifiers 1. * – 0 or more occurrences (Greedy) Description: Matches the preceding element zero or more times Example 1: Match zero or more digits python import re text = “123 4567 89″ result = re.findall(r’\d*’, text) print(result) # [‘123’, ”, ‘4567’, ”, ’89’, ”] # Matches…

  • Predefined Character Classes

    Predefined Character Classes Pattern Description Equivalent . Matches any character except newline \d Matches any digit [0-9] \D Matches any non-digit [^0-9] \w Matches any word character [a-zA-Z0-9_] \W Matches any non-word character [^a-zA-Z0-9_] \s Matches any whitespace character [ \t\n\r\f\v] \S Matches any non-whitespace character [^ \t\n\r\f\v] 1. Literal Character a Matches: The exact character…

  • Method Overloading

    Python does not support traditional method overloading in the way languages like C++ or Java do. If you define multiple methods with the same name, the last definition will simply overwrite all previous ones. However, you can achieve the same result—making a single method behave differently based on the number or type of arguments—using Python’s…

  • recursive function

    A recursive function is a function that calls itself to solve a problem. It works by breaking down a larger problem into smaller, identical subproblems until it reaches a base case, which is a condition that stops the recursion and provides a solution to the simplest subproblem. The two main components of a recursive function…

Leave a Reply

Your email address will not be published. Required fields are marked *