Iterables and iterators

INPUT · Slides

Doing a for loop by hand

01 / 07

Ask for the helper yourself

Get hold of that "give them out one at a time" helper for yourself. The tool is iter. Give it an iterable and an iterator comes back.

fruits = ["apple", "orange"]it = iter(fruits)print(it)<list_iterator object at 0x1234abcd>

The name it is only the front of iterator. You see it written that way all over Python code.

02 / 07

next hands you the next value

To ask that helper for the next value you use next. Call it and the next one comes back, every time.

Look at how the same next(it) gives a different value on each of its three lines. The iterator remembers how far it has got.

fruits = ["apple", "orange", "grape"]it = iter(fruits)print(next(it))print(next(it))print(next(it))

Result

apple
orange
grape

03 / 07

Ask once too often and it complains

What happens if there is only one thing inside and you ask twice? You get StopIteration.

The name says it: repeating stops here. That is the signal for has been catching all along, so that it could end the loop quietly.

it = iter(["apple"])print(next(it))print(next(it))

Result

apple
StopIteration

04 / 07

Give it a fallback and it will not stop

next takes a second argument: the value to hand back when there is nothing left.

Write next(it, "the end") and running out gives you the end rather than an error. It saves you writing anything to catch the error, which is worth remembering.

it = iter(["apple"])print(next(it, "the end"))print(next(it, "the end"))

Result

apple
the end

05 / 07

Write a for loop out longhand

With what you have now you can write out what for does. Get an iterator, then keep asking until there is nothing left.

The code below and for fruit in fruits: do exactly the same thing. Being longer, it lets you see what goes on inside.

fruits = ["apple", "orange"]it = iter(fruits)next_one = next(it, None)while next_one is not None:    print(next_one)    next_one = next(it, None)

Result

apple
orange

06 / 07

An iterator does not go back

One important thing about them. Use an iterator up and you cannot loop over it again. There is no rewinding.

In the example below the second for produces nothing at all, because the iterator has already handed everything out.

When you want to go round more than once, loop over the list instead. A list builds a new helper each time it is asked.

it = iter(["apple", "orange"])for fruit in it:    print(fruit)print("second time")for fruit in it:    print(fruit)print("done")

Result

apple
orange
second time
done

07 / 07

In short

So this is what for really is.

  • iter gets you an iterator
  • next gets you the next value
  • StopIteration arriving ends it

No magic left. Write for from day to day by all means, but knowing the inside is what lets you read the documentation.

From the next lesson you learn two tools you will use daily. This is where it turns practical.