♾️ Python Generators — Memory-Efficient Iterators
Generators produce values on demand instead of storing everything in memory. Perfect for large datasets, streaming, and infinite sequences.
Use generators when processing large files, streams, or infinite sequences. For small data, regular lists are easier.
💻 Code Example:
# 1. Generator function with yield def count_up(limit): """Generates numbers from 0 to limit — one at a time.""" n = 0 while n < limit: yield n # Pauses here and returns n n += 1 # Only ~48 bytes memory — regardless of how large limit is! gen = count_up(1_000_000) print(next(gen)) # 0 print(next(gen)) # 1 # 2. Generator expression (like list comp but lazy) large_squares = (x**2 for x in range(1_000_000)) # List would use 8MB; generator uses ~128 bytes! # 3. Real-world use: reading a huge file line by line def read_large_pynfinity_log(filepath): with open(filepath, 'r') as f: for line in f: yield line.strip() # for log_entry in read_large_pynfinity_log('app.log'): # process(log_entry) # 4. Infinite sequence generator def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b fib = fibonacci() first_10 = [next(fib) for _ in range(10)] print(first_10) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
| Concept | Key Takeaway |
|---|---|
| yield | Pauses function and returns a value — resumes on next call |
| Generator expression | (x for x in iterable) — lazy version of list comp |
| Memory | Lists store all elements; generators compute one at a time |
| send() | Can SEND a value BACK into a generator (bidirectional) |
Keep exploring and happy coding! 🚀