Advanced Patterns: Decorators & Generators
Python provides unique features that allow you to write highly efficient and extensible code. Decorators and Generatorsare two of the most powerful.
1. Decorators (@)
Decorators allow you to wrap another function in order to extend the behavior of the wrapped function, without permanently modifying it.
def my_decorator(func):
def wrapper():
print("--- Start ---")
func()
print("--- End ---")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
2. Generators (yield)
Generators are functions that allow you to declare a function that behaves like an iterator. They use the yield keyword to return data lazily.
def count_up_to(max):
count = 1
while count <= max:
yield count # Pause here
count += 1
counter = count_up_to(5)
for n in counter:
print(n)
Why use Generators?
Generators are memory-efficient. Instead of creating a huge list in memory, they generate one item at a time only when needed. This is critical for processing massive data files.
Note: Most modern Python frameworks (like Flask and FastAPI) use decorators heavily for routing and dependency injection.