The Iterator Protocol
Understand __iter__ and __next__.
The Iterator Protocol is a free Python Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is Iteration?
Whenever you write a for loop over a list, string, or dict, Python is using the iterator protocol behind the scenes.
An object you can loop over is called an iterable. The thing that actually produces values one at a time is called an iterator.
for ch in 'abc':
print(ch)iter() and next()
Two built-in functions drive iteration:
iter(obj)asks an iterable for its iterator.next(it)asks the iterator for the next value.
When there are no more values, next() raises StopIteration.
it = iter([10, 20, 30])
print(next(it))
print(next(it))
print(next(it))StopIteration
Calling next() one time too many raises StopIteration. A for loop catches this automatically and stops cleanly.
it = iter([1])
print(next(it))
try:
next(it)
except StopIteration:
print('No more items')The Two Dunder Methods
To make your own iterator you implement two methods:
__iter__returns the iterator object itself.__next__returns the next value or raisesStopIteration.
class Count:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
for x in Count(3):
print(x)Iterable vs Iterator
An iterable only needs __iter__. An iterator needs both __iter__ and __next__.
Lists are iterable but not iterators: each call to iter() gives a fresh iterator.
nums = [1, 2, 3]
print(iter(nums) is iter(nums))
it = iter(nums)
print(it is iter(it))Iterators Are Exhausted Once
An iterator can be consumed only once. After you reach the end, it stays empty. To loop again, create a new iterator.
it = iter([1, 2])
print(list(it))
print(list(it))A Range-Like Iterator
Let's build a custom iterator that behaves like a simple counter. Notice how state lives in the instance.
class EvenUpTo:
def __init__(self, limit):
self.cur = 0
self.limit = limit
def __iter__(self):
return self
def __next__(self):
if self.cur > self.limit:
raise StopIteration
value = self.cur
self.cur += 2
return value
print(list(EvenUpTo(8)))Separating Iterable and Iterator
A cleaner design keeps the container and the iterator separate, so the container can be looped many times.
class Bag:
def __init__(self, items):
self.items = items
def __iter__(self):
return BagIterator(self.items)
class BagIterator:
def __init__(self, items):
self.items = items
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i >= len(self.items):
raise StopIteration
v = self.items[self.i]
self.i += 1
return v
b = Bag(['x', 'y'])
print(list(b))
print(list(b))Using next() With a Default
next(it, default) returns the default instead of raising StopIteration when the iterator is empty. Handy for safe peeking.
it = iter([42])
print(next(it, 'done'))
print(next(it, 'done'))Iterators Are Memory Friendly
Iterators yield one item at a time, so they do not need to hold the whole sequence in memory. This is why they scale to huge or even infinite streams.
class Naturals:
def __init__(self):
self.n = 0
def __iter__(self):
return self
def __next__(self):
self.n += 1
return self.n
it = iter(Naturals())
print(next(it), next(it), next(it))Built-ins That Consume Iterators
Many built-ins accept any iterator: sum, max, min, sorted, list, tuple. They pull values until StopIteration.
class Count:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
print(sum(Count(5)))
print(max(Count(5)))Quick Check
Test your understanding of the iterator protocol.
Recap
You learned the iterator protocol:
iter()gets an iterator;next()pulls values.StopIterationsignals the end andforhandles it.- Custom iterators implement
__iter__and__next__. - Iterators are single-use and memory friendly.
Next you'll let Python write iterators for you with yield.
Frequently asked questions
Is the “The Iterator Protocol” lesson free?
Yes — the full text of “The Iterator Protocol” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.
What will I learn in “The Iterator Protocol”?
Understand __iter__ and __next__. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Python Academy?
No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “The Iterator Protocol” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Python Academy lesson?
Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Iterator Protocol
- Generator Functions
- Generator Expressions
- yield from and Delegation