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

  • re.sub()

    Python re.sub() Method Explained The re.sub() method is used for searching and replacing text patterns in strings. It’s one of the most powerful regex methods for text processing. Syntax python re.sub(pattern, repl, string, count=0, flags=0) Example 1: Basic Text Replacement python import re text = “The color of the sky is blue. My favorite color is blue too.” #…

  • Functions as Objects

    Functions as Objects and First-Class Functions in Python In Python, functions are first-class objects, which means they can be: 1. Functions as Objects In Python, everything is an object, including functions. When you define a function, you’re creating a function object. python def greet(name): return f”Hello, {name}!” # The function is an object with type ‘function’…

  • Finally Block in Exception Handling in Python

    Finally Block in Exception Handling in Python The finally block in Python exception handling executes regardless of whether an exception occurred or not. It’s always executed, making it perfect for cleanup operations like closing files, database connections, or releasing resources. Basic Syntax: python try: # Code that might raise an exception except SomeException: # Handle the exception else:…

  • Built-in Object & Attribute Functions in python

    1. type() Description: Returns the type of an object. python # 1. Basic types print(type(5)) # <class ‘int’> print(type(3.14)) # <class ‘float’> print(type(“hello”)) # <class ‘str’> print(type(True)) # <class ‘bool’> # 2. Collection types print(type([1, 2, 3])) # <class ‘list’> print(type((1, 2, 3))) # <class ‘tuple’> print(type({1, 2, 3})) # <class ‘set’> print(type({“a”: 1})) # <class…

  • Create a User-Defined Exception

    A user-defined exception in Python is a custom error class that you create to handle specific error conditions within your code. Instead of relying on built-in exceptions like ValueError, you define your own to make your code more readable and to provide more specific error messages. You create a user-defined exception by defining a new…

  • 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…

Leave a Reply

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