Der Iterator selbst dreht sich möglicherweise nicht aufgrund von "break" usw. zum Ende, aber es gibt seltene Fälle, in denen Sie die Iteration im Generator zum Ende drehen möchten.
Als Beispiel fügt das folgende "range_printsum" den Vorgang des Druckens der Summe des Bereichs zur Funktion "range" hinzu.
gen.py
def range_printsum(*args, **kwargs):
sum_ = 0
for i in range(*args, **kwargs):
sum_ += i
yield i
print(sum_)
Wenn in dieser Generatorimplementierung die Iteration in der Mitte gestoppt wird, ist das, was tatsächlich in "sum_" gespeichert ist, die Gesamtzahl der "Erträge", und "sum_" wird überhaupt nicht ausgegeben.
>>> from gen import range_printsum
>>> for i in range_printsum(11):
... pass
...
55
>>> for i in range_printsum(11):
... if i > 5:
... break
...
>>>
Erfassen Sie also "Generator Exit". Dies wird gesendet, wenn der Generator geschlossen ist (wenn der Generator close ()
aufgerufen wird). Dies kann auch dann erfasst werden, wenn die Schleife wie "for" unterbrochen ist.
Ändern Sie nach der Erfassung von "GeneratorExit" "range_printsum" so, dass kein Wert zurückgegeben und nur addiert wird.
gen.py
def range_printsum(*args, **kwargs):
sum_ = 0
stop_yield = False
for i in range(*args, **kwargs):
sum_ += i
if not stop_yield:
try:
yield i
except GeneratorExit:
stop_yield = True
print(sum_)
Diesmal funktioniert es wie erwartet.
>>> from gen import range_printsum
>>> for i in range_printsum(11):
... pass
...
55
>>> for i in range_printsum(11):
... if i > 5:
... break
...
55
>>>
Es funktioniert auch, wenn es so unterbrochen wird.
>>> try:
... for i in range_printsum(11):
... if i > 5:
... raise IndexError
... except IndexError:
... pass
...
55
>>>
Als Einschränkung der Generatorspezifikationen darf ein einmal geschlossener Generator keinen Wert erzeugen. Wenn Sie nach der Erfassung des "GeneratorExit" einen Wert "ergeben", wird der Fehler "RuntimeError: Generator ignoriert GeneratorExit" angezeigt.
Recommended Posts