guarding for StopIteration (WAS: Help with generators outside of loops.)

Steven Bethard steven.bethard at gmail.com
Wed Dec 8 03:36:18 EST 2004


David Eppstein wrote:
> I've made it a policy in my own code to always surround explicit calls 
> to next() with try ... except StopIteration ... guards.
> 
> Otherwise if you don't guard the call and you get an unexpected 
> exception from the next(), within a call chain that includes a for-loop 
> over another generator, then that other for-loop will terminate without 
> any error messages and the cause of its termination can be very 
> difficult to track down.

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.:

 >>> def g():
... 	raise StopIteration
...
 >>> class C(object):
...     def __iter__(self):
...         for i in range(3):
...             yield i
...             g()
...
 >>> for i in C():
... 	print i
...
0
 >>>

A StopIteration raised within the body of a for-loop will not cause it 
to terminate silently; the StopIteration exception will be propagated 
upward:

 >>> def g():
... 	raise StopIteration
...
 >>> def f(n):
...     for i in range(n):
...         print i
...         g()
...
 >>> f(3)
0
Traceback (most recent call last):
   File "<interactive input>", line 1, in ?
   File "<interactive input>", line 4, in f
   File "<interactive input>", line 2, in g
StopIteration
 >>>


Steve



More information about the Python-list mailing list