HTML

    Select a Subtopic

    Day 14: Decorators and Generators

    Today, we will focus on two important concepts in Python: Decorators and Generators. Both are powerful tools that help you write more efficient, readable, and maintainable code.

    1. Decorators

    A decorator is a function that wraps another function or method, allowing you to modify its behavior without changing its actual code.

    Function Decorators

    A decorator is typically used for:

    • Adding logging
    • Measuring execution time
    • Checking permissions

    How Do Decorators Work?

    A decorator is a function that takes another function as input and returns a new function that enhances or modifies the behavior of the original function.

    Creating a Simple Decorator

    def simple_decorator(func): def wrapper(): print("Before the function call") func() # Call the original function print("After the function call") return wrapper # Using the decorator @simple_decorator def say_hello(): print("Hello!") say_hello()

    Output:

    Before the function call Hello! After the function call

    Decorator with Arguments

    def decorator_with_args(func): def wrapper(*args, **kwargs): print("Before the function call") result = func(*args, **kwargs) # Passing arguments to the original function print("After the function call") return result return wrapper @decorator_with_args def greet(name): print(f"Hello, {name}!") greet("Alice")

    Output:

    Before the function call Hello, Alice! After the function call

    Built-in Decorators

    Python provides some built-in decorators like @staticmethod, @classmethod, and @property. These decorators modify methods in classes, making them static or class-bound, or turning them into properties.

    2. Generators

    Generators are a type of iterable, like lists or tuples, but instead of storing all the values in memory, they yield values one at a time, which is more memory-efficient.

    Why Use Generators?

    Generators allow you to work with large data sets efficiently because they don't require storing everything in memory.

    Creating a Generator

    def fibonacci(n): a, b = 0, 1 while n > 0: yield a a, b = b, a + b n -= 1 # Using the generator for num in fibonacci(5): print(num)

    Output:

    0 1 1 2 3

    Generator Expression

    gen = (x*x for x in range(5)) for num in gen: print(num)

    Output:

    0 1 4 9 16

    Advantages of Generators

    • Memory Efficient: Generators produce values on the fly, so they don’t need to store the entire result set in memory.
    • Lazy Evaluation: Values are computed only when needed, making generators faster for large data sets.

    Exercises for Day 14

    1. Create a Function Decorator for Logging
    2. Timing Decorator
    3. Create a Fibonacci Generator
    4. Create a Prime Number Generator

    Recap

    By the end of **Day 14**, you'll have a solid understanding of how to use decorators and generators to write more elegant and efficient Python code. Would you like any more specific examples or further explanation?