Python Decorators & Generators
PythonThese are intermediate-to-advanced concepts that show up in interviews and real projects.
Key Points
- Decorators — wrap a function to add extra behavior
- Use
@decorator_namesyntax above a function - Generators — produce values lazily using
yield - Generators are memory-efficient for large data
- Both are heavily used in frameworks like Flask and Django
Example — PYTHON
# Decorator basics
def timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end-start:.4f}s")
return result
return wrapper
@timer
def slow_add(a, b):
import time
time.sleep(0.1)
return a + b
result = slow_add(10, 20)
print(f"Result: {result}")
# Practical decorator — login required
def login_required(func):
def wrapper(user, *args, **kwargs):
if not user.get("logged_in"):
print("Access denied! Please login. ❌")
return
return func(user, *args, **kwargs)
return wrapper
@login_required
def dashboard(user):
print(f"Welcome to dashboard, {user['name']}! ✅")
dashboard({"name": "Rahul", "logged_in": True})
dashboard({"name": "Guest", "logged_in": False})
# Generator basics
def countdown(n):
while n > 0:
yield n
n -= 1
for num in countdown(5):
print(num, end=" ")
print()
# Generator for large data (memory efficient)
def fibonacci(limit):
a, b = 0, 1
while a < limit:
yield a
a, b = b, a + b
fib = list(fibonacci(100))
print(f"Fibonacci: {fib}")
# Generator expression (like list comp but lazy)
squares_gen = (x**2 for x in range(1, 1000001))
print(f"First 5 squares: {[next(squares_gen) for _ in range(5)]}") Result
slow_add took 0.1003s
Result: 30
Welcome to dashboard, Rahul! ✅
Access denied! Please login. ❌
5 4 3 2 1
Fibonacci: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
First 5 squares: [1, 4, 9, 16, 25]
Result: 30
Welcome to dashboard, Rahul! ✅
Access denied! Please login. ❌
5 4 3 2 1
Fibonacci: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
First 5 squares: [1, 4, 9, 16, 25]