0%

Iteration as an Interface · practice

Use iter() and next()

A for is a convenience. Underneath it are two calls you can make yourself, and making them once removes most of the mystery.

Driving a loop by hand

Try it

iter() asks for the . next() asks it for one item and moves it forward. That is the entire protocol on the caller’s side.

Ask once more and the iterator has to say something:

next(walker)

StopIteration. Not a bug, not an error in your code: it is how an iterator reports that there is nothing left. The is the message.

What for is doing

Knowing those two calls, you can write the loop out longhand:

Try it

Same output as for question in questions. Every for loop you have ever written is this, and this is why a for loop never raises StopIteration at you: catching it and stopping is the loop’s job.

What does a for loop do with StopIteration?

A default instead of an exception

next() takes a second , returned instead of raising when the iterator is finished:

Try it

This is worth knowing because it turns “take the next thing, if there is one” from four lines into one. It is the right tool when running out is an ordinary outcome, and the wrong one when running out means something went wrong and you want to hear about it.

What this is actually for

Most of the time you should write for, and this lesson is not an argument otherwise. Reaching for iter() and next() directly is worth it in a few real situations:

Taking one item, then looping over the rest. A file’s first line is a header, and the rest are data:

lines = iter(all_lines)
header = next(lines)

for line in lines:
    ...

The for loop continues from where next() left the position, because there is one iterator and both share it. That only works because of the split from Lesson 1.

Taking one item safely. next(walker, None) answers “is there anything?” and hands you that item at the same time. The iterator advances; this is a read, not a peek.

Walking two sequences at different speeds. When zip() does not fit because one side sometimes advances twice.

If you find yourself writing while True with a try around next(), you have rewritten for. Write for.

Task

Use iter() and next() directly for the three jobs where they earn their place.

split_header(lines) returns the first line and a of the rest. Take one item with next(), then over the same for the remainder. An empty input returns (None, []).

first_or(items, fallback) returns the first item, or fallback when there is none. Use the two- form of next() rather than a try.

count_by_hand(items) counts the items using while True, next(), and except StopIteration rather than a for loop. You would not write this in real code, and writing it once is how the loop stops being magic.

Run the program and check that split_header returns the remaining two lines, not all three.