# PEP on breaking outer loops with StopIteration

Kris Kowal kris.kowal at cixar.com
Tue Jun 10 03:07:30 CEST 2008

```I had a thought that might be pepworthy.  Might we be able to break
outer loops using an iter-instance specific StopIteration type?

This is the desired, if not desirable, syntax::

import string
letters = iter(string.lowercase)
for letter in letters:
for number in range(10):
print letter, number
if letter == 'a' and number == 5:
raise StopIteration()
if letter == 'b' and number == 5:
raise letters.StopIteration()

The first StopIteration would halt the inner loop.  The second
StopIteration would halt the outer loop.  The inner for-loop would
note that the letters.StopIteration instance is specifically targeted
at another iteration and raise it back up.

For this output::

a 0
a 1
a 2
a 3
a 4
a 5
b 0
b 1
b 2
b 3
b 4
b 5

This could be incrementally refined with the addition of an "as"
clause to "for" that would be bound after an iterable is implicitly
iter()ed::

import string
for letter in string.lowercase as letters:
…
raise letters.StopIteration()

I took the liberty to create a demo using a "for_in" decorator instead
of a "for" loop::

former_iter = iter

class iter(object):
def __init__(self, values):
if hasattr(values, 'next'):
self.iter = values
else:
self.iter = former_iter(values)
class Stop(StopIteration):
pass
if hasattr(values, 'StopIteration'):
self.StopIteration = values.StopIteration
else:
self.StopIteration = Stop

def next(self):
try:
return self.iter.next()
except StopIteration, exception:
raise self.StopIteration()

def for_in(values):
def decorate(function):
iteration = iter(values)
while True:
try:
function(iteration.next())
except iteration.StopIteration:
break
except StopIteration, exception:
if type(exception) is StopIteration:
break
else:
raise
return decorate

import string
letters = iter(string.lowercase)

@for_in(letters)
def _as(letter):
@for_in(range(10))
def _as(number):
print letter, number
if letter == 'a' and number == 5:
raise StopIteration()
if letter == 'b' and number == 5:
raise letters.StopIteration()

I imagine that this would constitute a lot of overhead in
StopIteration type instances, but perhaps a C implementation would use
flyweight StopIteration types for immutable direct subtypes of the
builtin StopIteration.

Kris Kowal

```