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
- Create a Function Decorator for Logging
- Timing Decorator
- Create a Fibonacci Generator
- 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?