Facebook Twitter Instagram
    TecAdmin
    • Home
    • FeedBack
    • Submit Article
    • About Us
    Facebook Twitter Instagram
    TecAdmin
    You are at:Home»Python Tips & Tricks»10 Powerful Python Decorators You Should Know

    10 Powerful Python Decorators You Should Know

    By RahulApril 19, 20234 Mins Read

    Python decorators are a versatile and powerful feature that allows you to extend or modify the behavior of functions and methods without altering their code. They enable the implementation of various tasks, such as logging, memoization, and access control, in a clean and maintainable manner. In this article, we will explore 10 powerful Python decorators you should know to enhance your programming skills and write more efficient code.

    1. Using Built-in Decorators

    Python provides several built-in decorators that simplify common tasks in object-oriented programming. These decorators include @property, @staticmethod, and @classmethod.

    @property: The @property decorator allows you to create read-only properties for a class. This decorator turns a method into a read-only attribute that can be accessed without calling the method like a function.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Circle:
        def __init__(self, radius):
            self._radius = radius
     
        @property
        def radius(self):
            return self._radius
     
    circle = Circle(5)
    print(circle.radius)  # Output: 5

    @staticmethod: The @staticmethod decorator is used to create static methods within a class, which do not have access to the instance or class attributes. These methods can be called on the class itself, without creating an instance.

    1
    2
    3
    4
    5
    6
    7
    class Math:
        @staticmethod
        def add(a, b):
            return a + b
     
    result = Math.add(1, 2)
    print(result)  # Output: 3

    @classmethod: The @classmethod decorator allows you to create class methods, which have access to the class itself but not the instance attributes. These methods can be called on the class or its instances.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Employee:
        _count = 0
     
        def __init__(self, name):
            self.name = name
            Employee._count += 1
     
        @classmethod
        def count(cls):
            return cls._count
     
    employee1 = Employee("Alice")
    employee2 = Employee("Bob")
    print(Employee.count())  # Output: 2

    2. Implementing Memoization with Decorators

    Memoization is a technique to cache the results of function calls to speed up the execution of repetitive computations. You can use a decorator to implement memoization, as shown below:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def memoization_decorator(func):
        cache = {}
     
        def wrapper(*args):
            if args not in cache:
                cache[args] = func(*args)
            return cache[args]
     
        return wrapper
     
    @memoization_decorator
    def fibonacci(n):
        if n <= 1:
            return n
        else:
            return fibonacci(n - 1) + fibonacci(n - 2)
     
    print(fibonacci(30))  # Output: 832040

    3. Adding Logging Functionality Using Decorators

    Decorators can be used to log information about function calls, such as the function name, arguments, and results. This can be helpful for debugging and monitoring your application.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import logging
     
    def logging_decorator(func):
        def wrapper(*args, **kwargs):
            logging.info(f"Called {func.__name__} with args {args} and kwargs {kwargs}")
            result = func(*args, **kwargs)
            logging.info(f"{func.__name__} returned {result}")
            return result
        return wrapper
     
    @logging_decorator
    def add(a, b):
        return a + b
     
    result = add(1, 2)

    4. Timing Function Execution with Decorators

    Use a decorator to measure the execution time of a function, which can be helpful for optimizing your code and identifying performance bottlenecks.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import time
     
    def timing_decorator(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()
            print(f"{func.__name__} took {end_time - start_time:.2f} seconds to execute.")
            return result
        return wrapper
     
    @timing_decorator
    def slow_function():
        time.sleep(2)
     
    slow_function()

    5. Implementing Access Control and Authentication with Decorators

    Decorators can be used to restrict access to specific functions based on user roles or credentials. This can be helpful for implementing access control and authentication in web applications or APIs.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def admin_required(func):
        def wrapper(user, *args, **kwargs):
            if user.is_admin():
                return func(user, *args, **kwargs)
            else:
                raise PermissionError("Admin access required.")
        return wrapper
     
    @admin_required
    def sensitive_operation(user):
        print("Performing sensitive operation...")
     
    # Assuming 'user' is an instance of a User class with an is_admin() method
    # sensitive_operation(user)

    6. Using Decorators for Input Validation

    Decorators can be employed to validate the input of a function before calling it. This can help prevent errors and ensure that the function only processes valid input.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def positive_numbers(func):
        def wrapper(a, b):
            if a > 0 and b > 0:
                return func(a, b)
            else:
                raise ValueError("Both arguments must be positive numbers.")
        return wrapper
     
    @positive_numbers
    def add(a, b):
        return a + b
     
    # add(1, -2)  # Raises ValueError

    7. Simplifying Context Management with Decorators

    Decorators can be used to simplify context management tasks, such as opening and closing files, by automatically handling these tasks within the decorator.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from contextlib import contextmanager
     
    @contextmanager
    def open_file(file_name, mode):
        try:
            file = open(file_name, mode)
            yield file
        finally:
            file.close()
     
    with open_file("test.txt", "r") as f:
        contents = f.read()

    8. Applying Rate Limiting Using Decorators

    Rate limiting can be implemented using decorators to control the frequency at which a function can be called. This is particularly useful for APIs and web applications to prevent abuse or excessive resource usage.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import time
     
    def rate_limited(max_calls, time_interval):
        calls = 0
        start_time = time.time()
     
        def rate_limit_decorator(func):
            nonlocal calls, start_time
     
            def wrapper(*args, **kwargs):
                nonlocal calls, start_time
                current_time = time.time()
                if current_time - start_time >= time_interval:
                    calls = 0
                    start_time = current_time
                if calls < max_calls:
                    calls += 1
                    return func(*args, **kwargs)
                else:
                    raise Exception("Rate limit exceeded.")
            return wrapper
        return rate_limit_decorator
     
    @rate_limited(max_calls=3, time_interval=1)
    def limited_function():
        print("Function called.")
     
    # Calling 'limited_function' more than 3 times in 1 second will raise an exception.

    9. Creating Custom Decorators for Your Specific Needs

    When built-in and common decorators do not fulfill your requirements, you can create custom decorators to address your specific needs. Follow the steps outlined in the “Python Decorators Demystified: A Comprehensive Guide” article to create custom decorators.

    10. Combining Decorators for More Complex Functionality

    In some cases, you may need to combine multiple decorators to achieve more complex functionality. You can chain decorators by applying them one after the other to a single function. Keep in mind that the order of decorators is essential, as it determines the order in which they are executed.

    1
    2
    3
    4
    5
    6
    7
    8
    @logging_decorator
    @timing_decorator
    @memoization_decorator
    def expensive_operation(a, b):
        time.sleep(1)
        return a ** b
     
    result = expensive_operation(2, 3)

    In this example, the expensive_operation function is first memoized, then its execution time is measured, and finally, the logging information is collected. The order of decorators affects the behavior of the function.

    Conclusion

    Python decorators offer a versatile and powerful way to extend or modify the behavior of functions and methods without altering their code. This article has introduced you to 10 powerful Python decorators that can help you enhance your programming skills and write more efficient code. By understanding these decorators and how to combine them, you can create cleaner, more maintainable, and more effective applications.

    Decorators functions Python
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email WhatsApp

    Related Posts

    How to Create and Use Custom Python Module

    Performance Optimization with Pylint in Python

    Understanding Case Sensitivity in Python

    Add A Comment

    Leave A Reply Cancel Reply

    Advertisement
    Recent Posts
    • How to Create and Use Custom Python Module
    • How to Install and Use Podman on Ubuntu 22.04 & 20.04
    • Setting Up Laravel with Docker and Docker-compose
    • Setting Up Development Environments with PHP and Docker
    • Using Composer with Different PHP Versions in Linux
    Facebook Twitter Instagram Pinterest
    © 2023 Tecadmin.net. All Rights Reserved | Terms  | Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.