In this piece of code, why does using for result in no StopIteration
or is the for loop trapping all exceptions and then silently exiting?
In which case, why do we have the extraneous return?? Or is the
raise StopIteration caused by: return None?
#!/usr/bin/python3.1
def countdown(n):
print("counting down")
while n >= 9:
yield n
n -= 1
return
for x in countdown(10):
print(x)
c = countdown(10)
next(c)
next(c)
next(c)
Assuming StopIteration is being triggered by: return None.
When is GeneratorExit generated?
def countdown(n):
print("Counting down from %d" % n)
try:
while n > 0:
yield n
n = n - 1
except GeneratorExit:
print("Only made it to %d" % n)
If I manually do a:
c = countdown(10)
c.close() #generates GeneratorExit??
In which case why don't I see a traceback?
The
forloop listens forStopIterationexplicitly.The purpose of the
forstatement is to loop over the sequence provided by an iterator and the exception is used to signal that the iterator is now done;fordoesn't catch other exceptions raised by the object being iterated over, just that one.That's because
StopIterationis the normal, expected signal to tell whomever is iterating that there is nothing more to be produced.A generator function is a special kind of iterator; it indeed raises
StopIterationwhen the function is done (i.e. when it returns, so yes,return NoneraisesStopIteration). It is a requirement of iterators; they must raiseStopIterationwhen they are done; in fact, once aStopIterationhas been raised, attempting to get another element from them (throughnext(), or calling the.next()(py 2) or.__next__()(py 3) method on the iterator) must always raiseStopIterationagain.GeneratorExitis an exception to communicate in the other direction. You are explicitly closing a generator with ayieldexpression, and the way Python communicates that closure to the generator is by raisingGeneratorExitinside of that function. You explicitly catch that exception inside ofcountdown, its purpose is to let a generator clean up resources as needed when closing.A
GeneratorExitis not propagated to the caller; see thegenerator.close()documentation.