Python Iterators
Table of Contents + β
In the last lesson you learned about the pip Package Manager. You saw how to add code that other people wrote to your project. Now we go back inside Python itself. We will look at something you have used many times without knowing its name. Every time you write a for loop, an iterator is quietly doing the work. So let us pull back the curtain and see what is really happening.
π€ Why Iterators Matter
Here is the pain. You write for item in my_list: and it just works. But have you ever wondered how Python knows which item comes next? And how does it know when to stop?
If you do not understand this, then a few things will always feel like magic. Generators. Lazy data. Reading a huge file one line at a time. And magic is hard to fix when it breaks.
Iterators are the answer. An iterator is the small object that remembers where you are in a sequence. When you ask for the next item, it hands it to you.
π§© Iterable vs Iterator
These two words look almost the same. So people mix them up all the time. Let us make the difference clear.
- An iterable is something you can loop over. A list, a string, a tuple, a dictionary, a set. Think of it as a box full of items.
- An iterator is the thing that actually hands out the items, one at a time. It remembers the spot you are at.
Here is a simple way to picture it. Think of a Netflix watchlist. The watchlist itself is the iterable. It is the full box of shows. The little arrow that points at βthe next show to watchβ is the iterator. The watchlist does not move. The arrow does.
So an iterable is the data. An iterator is the reader walking through that data.
Note
Every iterator is also an iterable. But not every iterable is an iterator. A list is iterable, but it is not an iterator. You have to ask the list for an iterator first.
π Getting an Iterator with iter()
To turn an iterable into an iterator, you call the built-in iter() function. You pass it your iterable. It gives you back an iterator.
This code takes a normal list and asks it for an iterator.
shows = ["Stranger Things", "Wednesday", "Dark"]
reader = iter(shows)
print(type(shows))print(type(reader))Output
<class 'list'><class 'list_iterator'>See the difference in the types? shows is a list. But reader is a list_iterator. They are not the same kind of object. The reader is the arrow that knows how to walk through the list.
β‘οΈ Getting Items with next()
Now you have an iterator. You pull items out of it one at a time with the built-in next() function. Each call gives you the next item and moves the arrow forward.
This code asks for the items one by one, by hand.
shows = ["Stranger Things", "Wednesday", "Dark"]reader = iter(shows)
print(next(reader))print(next(reader))print(next(reader))Output
Stranger ThingsWednesdayDarkNotice that the iterator remembers its place between calls. The first next() gives the first show. The second next() does not start over. It carries on from where it stopped. That memory of βwhere am Iβ is the whole point of an iterator.
β What Happens When Items Run Out
So what if you call next() one more time, after the last item is gone? The iterator has nothing left to give. So it raises an error called StopIteration.
This code goes one step too far on purpose, so you can see the error.
colors = ["red", "green"]reader = iter(colors)
print(next(reader))print(next(reader))print(next(reader)) # nothing left hereOutput
redgreenTraceback (most recent call last): File "main.py", line 7, in <module> print(next(reader))StopIterationNote
The exact file name and line number in that traceback will look a little different on your computer. That part depends on your file and your Python version. The line that matters is the last one, StopIteration.
StopIteration is not a bug. It is a signal. It is the iteratorβs way of saying βthat is everything, there is no next item.β Hold on to this idea. It explains the next part.
π How a for Loop Really Works
Here is the part that ties it all together. A for loop is not magic. Inside, it does exactly what you just did by hand.
When you write a normal for loop, Python quietly does this for you.
- It calls
iter()on your iterable to get an iterator. - It calls
next()again and again to pull out each item. - When
next()raisesStopIteration, the loop catches it and stops cleanly.
So this friendly loop:
for color in ["red", "green"]: print(color)is really doing this longer thing in the background:
colors = ["red", "green"]reader = iter(colors)
while True: try: color = next(reader) except StopIteration: break print(color)Both print the same output.
Output
redgreenSo now you can see it. The for loop is just a clean wrapper around iter() and next(). It catches the StopIteration for you. You never had to write the while True and the try/except yourself. The loop hides that work.
π The Two Pieces Side by Side
Here is a small table to keep the two words straight in your head.
| Idea | What it is | Example |
|---|---|---|
| Iterable | Something you can loop over | list, string, tuple, dict, set |
| Iterator | The object that hands out items one by one | the result of iter(my_list) |
iter() | Turns an iterable into an iterator | reader = iter(shows) |
next() | Pulls the next item from an iterator | next(reader) |
StopIteration | The signal that there is nothing left | raised after the last item |
β οΈ Common Mistakes
A few things trip people up when they first meet iterators.
Calling next() on a plain list. A list is an iterable, not an iterator. So this fails. You must call iter() first.
# β Avoid: a list is not an iteratorshows = ["Wednesday", "Dark"]print(next(shows)) # TypeError: 'list' object is not an iterator
# β
Good: get an iterator firstshows = ["Wednesday", "Dark"]reader = iter(shows)print(next(reader))Expecting an iterator to refill itself. Once an iterator reaches the end, it stays empty. Looping over it again gives you nothing.
# β Avoid: the second loop prints nothingreader = iter([1, 2, 3])for n in reader: print(n)for n in reader: # iterator is already used up print(n)
# β
Good: get a fresh iterator each timedata = [1, 2, 3]for n in iter(data): print(n)for n in iter(data): # a brand new arrow at the start print(n)Letting StopIteration crash your program. If you call next() by hand past the end and do not handle it, your program stops with an error. You can catch it. Or you can pass a default value as the second argument. With next(reader, "done"), you get back "done" instead of the error.
β Best Practices
Keep these small habits and iterators will stay easy.
- Reach for a plain
forloop most of the time. It callsiter()andnext()for you and handlesStopIterationcleanly. - Use
iter()andnext()by hand only when you truly need one item at a time. Reading the first line of a file and stopping is a good example. - When you call
next()by hand, give it a default value, likenext(reader, None). This is safer than wrapping everything intry/except. - Remember that an iterator is single-use. If you need to walk the data again, build a fresh iterator from the original iterable.
π§© What Youβve Learned
A quick recap of the ideas you now have.
- β An iterable is anything you can loop over, like a list or a string.
- β An iterator is the object that hands you items one at a time and remembers your place.
- β
iter()turns an iterable into an iterator. - β
next()pulls the next item, and raisesStopIterationwhen nothing is left. - β
A
forloop usesiter()andnext()inside and catchesStopIterationfor you. - β An iterator is single-use, so make a fresh one when you need to start over.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What is the difference between an iterable and an iterator?
Why: The iterable is the data you loop over, and the iterator is the object that hands out each item and remembers your place.
- 2
What does iter(my_list) return?
Why: iter() takes an iterable and gives you back an iterator that walks through its items.
- 3
What happens when you call next() on an iterator that has no items left?
Why: Once the items run out, next() raises StopIteration to signal there is nothing more to give.
- 4
How does a normal for loop work inside?
Why: A for loop calls iter() to get an iterator, calls next() for each item, and stops cleanly when StopIteration appears.
π Whatβs Next?
You now know how Python hands out items one at a time. Next we look at a clean way to build your own iterators without writing all that boilerplate by hand.