guarding for StopIteration (WAS: Help with generators outside of loops.)
Steven Bethard
steven.bethard at gmail.com
Wed Dec 8 03:48:43 EST 2004
Steven Bethard wrote:
> Just to clarify here, the only time code raising a StopIteration will
> cause a for-loop to exit silently is if the StopIteration is raised in
> an __iter__ method, e.g.:
That was a little imprecise. What I should have said is "the only time
code raising a StopIteration will cause a for-loop to exit silently is
if the StopIteration is raised in the code that is executed under the
iteration protocol."
So, using the legacy iterator protocol:
>>> class C:
... def __getitem__(self, index):
... if index > 3:
... raise IndexError
... if index == 1:
... raise StopIteration
... return index
...
>>> for i in C():
... print i
...
0
Or using a separate iterator object:
>>> class C(object):
... def __iter__(self):
... return I()
...
>>> class I(object):
... def __init__(self):
... self.count = -1
... def next(self):
... self.count += 1
... if self.count == 1:
... raise StopIteration
... return self.count
...
>>> for i in C():
... print i
...
0
Or using a generator to create the iterator object:
>>> class C(object):
... def __iter__(self):
... for i in range(3):
... if i == 1:
... raise StopIteration
... yield i
...
>>> for i in C():
... print i
...
0
Basically, each of these raises a StopIteration in the equivalent of the
.next method. If a function that raises a StopIteration is put into any
of the places where my code says 'raise StopIteration', then that
StopIteration will silently terminate the loop.
I don't believe there should be any other places where raising a
StopIteration would silently terminate a loop.
Steve
More information about the Python-list
mailing list