Python Iterators

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 Things
Wednesday
Dark

Notice 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 here

Output

red
green
Traceback (most recent call last):
File "main.py", line 7, in <module>
print(next(reader))
StopIteration

Note

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() raises StopIteration, 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

red
green

So 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 iterator
shows = ["Wednesday", "Dark"]
print(next(shows)) # TypeError: 'list' object is not an iterator
# βœ… Good: get an iterator first
shows = ["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 nothing
reader = 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 time
data = [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 for loop most of the time. It calls iter() and next() for you and handles StopIteration cleanly.
  • Use iter() and next() 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, like next(reader, None). This is safer than wrapping everything in try/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 raises StopIteration when nothing is left.
  • βœ… A for loop uses iter() and next() inside and catches StopIteration for 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. 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. 2

    What does iter(my_list) return?

    Why: iter() takes an iterable and gives you back an iterator that walks through its items.

  3. 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. 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.

Generators

Share & Connect