</>
Skip to content
Python lessons (26/45)

Python — Iterators

Every for loop uses this protocol

for x in [10, 20, 30]:
    print(x)

Under the hood:

it = iter([10, 20, 30])     # 1. get an iterator from the iterable
next(it)                    # 2. pull values one at a time → 10
next(it)                    # 20
next(it)                    # 30
next(it)                    # 💥 StopIteration → for catches it & ends
TermMeaningExamples
Iterablecan produce an iterator (iter() works)list, str, dict, file, range
Iteratorthe thing being pulled (next() works); remembers positionwhat iter() returns

Iterators are consumed — once exhausted they stay empty:

it = iter([1, 2])
list(it)      # [1, 2]
list(it)      # [] — already spent!

Building your own class-based iterator

class Countdown:
    def __init__(self, start):
        self.n = start

    def __iter__(self):
        return self              # the object is its own iterator

    def __next__(self):
        if self.n <= 0:
            raise StopIteration
        self.n -= 1
        return self.n + 1

for n in Countdown(3):
    print(n)          # 3, 2, 1

The duet: __iter__ returns the iterator; __next__ produces the next value or raises StopIteration.

Generators — iterators without ceremony

yield turns any function into a generator (an iterator factory):

def countdown(start):
    while start > 0:
        yield start         # pause here, hand out a value
        start -= 1

for n in countdown(3):
    print(n)

Same behavior as the class above with a tenth of the code. State persists between yields automatically.

Why generators matter: laziness

Values are produced ON DEMAND — nothing exists until asked:

def squares():
    n = 1
    while True:             # infinite!
        yield n * n
        n += 1

sq = squares()
next(sq)   # 1
next(sq)   # 4
next(sq)   # 9    — an infinite series in finite memory

Reading huge files line-by-line, streaming API data, infinite sequences — all generator territory.

Handy iteration tools

nums = [5, 3, 8]

sum(nums); max(nums); min(nums)       # consume any iterable
sorted(nums, reverse=True)
reversed(nums)                        # lazy reverse iterator

# itertools — iteration superpowers
from itertools import count, chain
chain([1], [2, 3])                    # 1,2,3 across containers
count(10, step=2)                     # infinite: 10,12,14…

Gotchas: reusing a spent iterator silently yields nothing · next(it) on empty raises unless you pass a default: next(it, None).

Mini Practice

  1. Manually iter/next a string; catch StopIteration.
  2. Prove exhaustion by consuming twice.
  3. Class-based Fibonacci iterator.
  4. Rewrite it as a generator; compare lines of code.
  5. Infinite even-numbers generator + islice to take five.

Next: polymorphism →

Related Topics

Frequently Asked Questions about Iterators

What is Iterators in Python?

Iterators is a fundamental concept in Python. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Iterators?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Iterators.

Why is Iterators important in Python?

Iterators is essential for Python development. Understanding this concept will help you write better code and solve real-world problems more effectively.