
Decorators and Generators in Python: A Powerful Duo Explained
Python is renowned for its robust features and ease of use. The capacity to build code that is clearer, more effective, and reusable makes decorators and generators stand out among them. Knowing these two ideas will improve your coding skills, whether you’re a novice moving into intermediate-level Python or getting ready for an interview.
What are Decorators in Python?
In Python, a decorator is a design pattern that lets you change a function’s or class method’s behavior without altering the source code.
Consider it similar to wrapping a present. You improve its appearance without changing the gift within.
Key Use Cases:
- Logging
- Authentication
- Caching
- Performance timing
- Access control
Basic Decorator Syntax
def my_decorator(func):
def wrapper():
print("Before the function runs.")
func()
print("After the function runs.")
return wrapper
@my_decorator
def greet():
print("Hello, World!")
greet()
Output:
Before the function runs.
Hello, World!
After the function runs.
Here, @my_decorator
is syntactic sugar for greet = my_decorator(greet)
Real-Life Example: Logging Decorator
def log_function(func):
def wrapper(*args, **kwargs):
print(f"Function '{func.__name__}' called with {args} and {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_function
def add(a, b):
return a + b
print(add(5, 3))
What are Generators in Python?
A generator is a function that, as opposed to returning all values at once as lists do, returns an iterator and gives values one at a time.
Generators save memory and are ideal for handling infinite sequences or big datasets.
Generator Syntax with yield
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
for number in count_up_to(5):
print(number)
Output:
1
2
3
4
5
The function preserves its state and continues where it left off each time it is called.
Use Case: Reading Large Files Line by Line
def read_large_file(file_path):
with open(file_path) as file:
for line in file:
yield line.strip()
for line in read_large_file("huge_file.txt"):
print(line)
Combining Decorators and Generators
Even generator functions can be decorated to provide timing or logging.
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
for value in func(*args, **kwargs):
yield value
end = time.time()
print(f"Execution took {end - start:.4f} seconds")
return wrapper
@timer
def generate_numbers():
for i in range(5):
time.sleep(0.5)
yield i
for num in generate_numbers():
print(num)
You can also read for:- What is the Python Standard Library?
Benefits of Using Decorators and Generators
Feature | Decorators | Generators |
---|---|---|
Code Reuse | Wrap functionality around others | Resume execution with yield |
Readability | Cleaner, DRY (Don’t Repeat Yourself) | Avoid large memory usage |
Flexibility | Can stack multiple decorators | Infinite or lazy sequences |
Performance | Add logging, caching, etc. easily | Efficient for loops and streams |
Summary
- Without altering the actual code, decorators improve or change methods and functions.
- With generators, you may use yield to iterate across huge or endless datasets.
- Both are sophisticated yet approachable Python ideas that result in scalable, clear code.
You also like this:-
Introduction to Serverless Databases: Firebase, AWS DynamoDB, & More
Top 10 Backend Frameworks in 2025: Which One Should You Choose?
What is Python Programming? Your Complete Guide to Understanding Python
Leave a Reply