Home > Back-end >  Raising `StopIteration` in loop body
Raising `StopIteration` in loop body

Time:12-10

I had always thought that a an exhausted iterator raises StopIteration, and a loop catches that. This seems to align with what's said in https://bugs.python.org/issue31156. Now, running any of

a=[1,3]
itr = iter(a)
while True:
    next(itr)
    next(itr)
    next(itr)

a=[1,3]
itr = iter(a)
for itr1 in itr:
    next(itr)
    next(itr)
    next(itr)

crashes. This seems not to align with what's said in the above link:

A StopIteration exception raised in the body of a while loop will terminate (and is caught by) the while-loop, thus leading to graceful termination.

Has the behaviour changed?

CodePudding user response:

A for loop like

for x in y:
    <body>

is roughly equivalent to

itr = iter(y)
while True:
    try:
        x = next(itr)
    except StopIteration:
        break

    <body>

(I say "roughly", because no name like itr is exposed to the body of the loop, I'm not handling the else clause of a for loop, etc.)

Notice that StopIteration is only caught when raised by the implicit call to next used to set the value of x, not if raised by something in the body of the loop.

Also note the last comment in the (now closed) issue from the reporter:

Sorry, that was my misinterpretation of what happened. I had been stumbling over an old program I had written, but apparently it works because the while-loop is inside a generator function, and the StopIteration is simply passed on.

  • Related