Skip to main content
Python for Beginners
CHAPTER 20 Beginner

Python Iterators and Generators

Updated: May 17, 2026
20 min read

# Python Iterators and Generators

Welcome to Chapter 20! Iterators and generators enable lazy evaluation — processing data one item at a time without loading everything into memory.

---

1. Learning Objectives

  • Understand the iterator protocol.
  • Create custom iterators.
  • Write generator functions with yield.
  • Use generator expressions.
  • Understand lazy vs eager evaluation.

---

2. Iterators

```python id="py20_ex1" # Every iterable has an iterator numbers = [1, 2, 3] iterator = iter(numbers)

print(next(iterator)) # 1 print(next(iterator)) # 2 print(next(iterator)) # 3 # print(next(iterator)) # StopIteration error!

# for loops use iterators internally for num in [10, 20, 30]: # Python calls iter() and next() behind the scenes print(num)

12
### Custom Iterator

python id="py20ex2" class Countdown: def init(self, start): self.start = start def iter(self): self.current = self.start return self def next_(self): if self.current <= 0: raise StopIteration val = self.current self.current -= 1 return val

for num in Countdown(5): print(num, end=" ") # 5 4 3 2 1

123456
---

## 3. Generators

Generators are the **easy way** to create iterators using `yield`:

python id="py20_ex3" def countdown(n): while n > 0: yield n # Pauses here, returns value n -= 1 # Resumes here on next call

for num in countdown(5): print(num, end=" ") # 5 4 3 2 1

# Generator produces values lazily (one at a time) gen = countdown(3) print(next(gen)) # 3 print(next(gen)) # 2 print(next(gen)) # 1

12
### Fibonacci Generator

python id="py20_ex4" def fibonacci(limit): a, b = 0, 1 while a < limit: yield a a, b = b, a + b

fibs = list(fibonacci(100)) print(fibs) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

1234
---

## 4. Generator Expressions

python id="py20ex5" # List comprehension (eager — creates entire list) squareslist = [x2 for x in range(1000000)] # Uses lots of memory!

# Generator expression (lazy — one at a time) squaresgen = (x2 for x in range(1000000)) # Almost no memory!

print(sum(squaresgen)) # Works, but memory efficient

# Use generators when you don't need the whole list total = sum(x**2 for x in range(100)) # No parentheses needed inside function print(total)

1234
---

## 5. yield vs return

python id="py20ex6" # return — ends function, sends one value def getsquareslist(n): result = [] for i in range(n): result.append(i2) return result # All at once

# yield — pauses function, sends values one at a time def getsquares_gen(n): for i in range(n): yield i2 # One at a time

1

return vs yield: return: [0, 1, 4, 9, 16] → All in memory at once yield: 0 → 1 → 4 → 9 → 16 → One at a time

1234
---

## 6. Practical: Reading Large Files

python id="py20ex7" def readlargefile(filepath): """Memory-efficient file reader""" with open(filepath, "r") as f: for line in f: yield line.strip()

# Process millions of lines without loading all into memory # for line in readlargefile("hugefile.txt"): # process(line) ``

---

7. MCQs with Answers

Q1: yield makes a function a: A) Class B) Generator C) Decorator D) Module Answer: B

Q2: Generators are: A) Eager B) Lazy C) Parallel D) Recursive Answer: B — They produce values on demand.

Q3: next() on exhausted iterator raises: A) ValueError B) IndexError C) StopIteration D) GeneratorExit Answer: C

Q4: Generator expression syntax uses: A) [] B) {} C) () D) <> Answer: C — Parentheses instead of square brackets.

Q5: Iterator protocol requires: A) _iter only B) next only C) Both iter and next D) call Answer: C

Q6: Generators are memory efficient because: A) They compress data B) They produce values one at a time C) They use caching D) They run faster Answer: B

Q7: yield vs return: A) Same B) yield pauses, return ends C) return pauses D) yield ends Answer: B

Q8: Can a generator be iterated twice? A) Yes B) No — it's exhausted after one pass Answer: B

Q9: sum(x for x in range(10)) uses: A) List B) Generator expression C) Tuple D) Set Answer: B

Q10: send() on generator: A) Sends value into generator B) Sends email C) Error D) Stops generator Answer: A

---

8. Interview Questions

  1. 1. Iterator vs Iterable? Iterable has iter() (lists, strings). Iterator has both iter() and next().
  1. 2. Why use generators? Memory efficiency — they don't store all values at once.
  1. 3. Can generators be infinite? Yes! while True: yield value. Use next() or islice() to consume.
  1. 4. What is yield from? Delegates to a sub-generator: yield from anothergenerator().
  1. 5. Generator vs list comprehension? Generators are lazy (memory efficient); list comprehensions create the full list.

---

9. Summary

  • Iterators implement _iter() and next_().
  • Generators use yield to produce values lazily.
  • Generator expressions use () instead of []`.
  • Generators are memory efficient — perfect for large datasets.
  • A generator can only be iterated once.

---

10. Next Chapter Recommendation

In Chapter 21: Python Decorators, you'll learn to modify function behavior without changing their code! 🚀

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·