What are Generators?
Generators are functions that return an iterator. They use yield instead of return and produce values one at a time, making them memory efficient.
Simple Generator
Create a generator function:
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
# Use the generator
for num in count_up_to(5):
print(num) # 1, 2, 3, 4, 5
Generator vs List
Generators are memory efficient:
# List - stores all values
def squares_list(n):
return [x**2 for x in range(n)]
# Generator - produces on demand
def squares_gen(n):
for x in range(n):
yield x**2
# Generator expression
squares = (x**2 for x in range(10))
Using next()
Manually iterate through generator:
gen = count_up_to(3)
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
# print(next(gen)) # StopIteration
Generator Expressions
Similar to list comprehensions:
# List comprehension
squares_list = [x**2 for x in range(10)]
# Generator expression
squares_gen = (x**2 for x in range(10))
# More memory efficient
print(sum(squares_gen)) # 285
Why Use Generators?
- Memory efficient: Don't store all values
- Lazy evaluation: Values computed when needed
- Infinite sequences: Can generate infinite data
- Pipeline processing: Chain generators together
Best Practices
- Use for large datasets: When memory is a concern
- Use generator expressions: For simple transformations
- Don't reuse generators: They're one-time use
- Consider itertools: For complex generator patterns
Next Steps
Learn about iterators and comprehensions.