Python Tutorial

Python Variable

Python Operators

Python Sequence

Python String

Python Flow Control

Python Functions

Python Class and Object

Python Class Members (properties and methods)

Python Exception Handling

Python Modules

Python File Operations (I/O)

Python @function decorator

A function decorator in Python is a function that takes another function as input and extends or modifies its behavior without changing its code. Decorators are a powerful way to implement aspect-oriented programming and can be used for a variety of tasks like logging, caching, or access control.

Here's a step-by-step tutorial on how to create and use function decorators in Python:

  • Define the decorator function: First, create a function that takes another function as an argument. This will be our decorator function. Inside the decorator function, define a new function (often called a "wrapper" function) that will extend or modify the behavior of the input function. Finally, return the wrapper function from the decorator function.
def my_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
  • Apply the decorator to a function: To apply the decorator to a function, use the @ syntax followed by the decorator function's name before the function definition. This is equivalent to passing the function to the decorator and reassigning the function's name to the returned wrapper function.
@my_decorator
def say_hello():
    print("Hello!")

# This is equivalent to:
# say_hello = my_decorator(say_hello)
  • Call the decorated function: When you call the decorated function, the wrapper function inside the decorator is executed, which in turn calls the original function with the extended behavior.
say_hello()

Output:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.
  • Decorators with arguments: If your decorator needs to accept arguments, you can define an outer function that takes the arguments and returns the actual decorator function.
def repeat_decorator(times):
    def actual_decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return actual_decorator

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

greet("John")

Output:

Hello, John!
Hello, John!
Hello, John!

This tutorial introduced the basics of creating and using function decorators in Python. You can use decorators to extend or modify the behavior of functions in a clean and reusable way. Experiment with different decorator use cases to get a better understanding of their capabilities and limitations.

  1. Python function decorators examples:

    def my_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
    
    @my_decorator
    def say_hello():
        print("Hello!")
    
    say_hello()
    
  2. How to use @decorator in Python:

    The @decorator syntax is a convenient way to apply a decorator to a function.

    def my_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
    
    @my_decorator
    def say_hello():
        print("Hello!")
    
    say_hello()
    
  3. Decorators in Python explained:

    Decorators are functions that wrap other functions, allowing you to modify or extend their behavior.

    def my_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
    
    @my_decorator
    def say_hello():
        print("Hello!")
    
    say_hello()
    
  4. Nested decorators in Python:

    def decorator1(func):
        def wrapper():
            print("Decorator 1")
            func()
        return wrapper
    
    def decorator2(func):
        def wrapper():
            print("Decorator 2")
            func()
        return wrapper
    
    @decorator1
    @decorator2
    def my_function():
        print("Original function")
    
    my_function()
    
  5. Creating custom decorators in Python:

    def my_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
    
    @my_decorator
    def say_hello():
        print("Hello!")
    
    say_hello()
    
  6. Decorator chaining in Python:

    def decorator1(func):
        def wrapper():
            print("Decorator 1")
            func()
        return wrapper
    
    def decorator2(func):
        def wrapper():
            print("Decorator 2")
            func()
        return wrapper
    
    @decorator1
    @decorator2
    def my_function():
        print("Original function")
    
    my_function()
    
  7. Decorator vs wrapper functions in Python:

    Decorators are applied using the @decorator syntax, while wrapper functions explicitly call and return the original function.

    def my_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
    
    @my_decorator
    def say_hello():
        print("Hello!")
    
    say_hello()
    
  8. Memoization with decorators in Python:

    from functools import lru_cache
    
    @lru_cache(maxsize=None)
    def fibonacci(n):
        if n <= 1:
            return n
        else:
            return fibonacci(n-1) + fibonacci(n-2)
    
    print(fibonacci(10))
    
  9. Error handling with decorators in Python:

    def error_handler(func):
        def wrapper(*args, **kwargs):
            try:
                result = func(*args, **kwargs)
                return result
            except Exception as e:
                print(f"An error occurred: {e}")
        return wrapper
    
    @error_handler
    def divide(a, b):
        return a / b
    
    result = divide(10, 0)
    
  10. Decorators for logging in Python:

    def log_decorator(func):
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            print(f"Function {func.__name__} executed with result: {result}")
            return result
        return wrapper
    
    @log_decorator
    def add(a, b):
        return a + b
    
    result = add(3, 5)