Beste Möglichkeit, den Rückgabewert von einem Python-Generator zu erhalten
Since Python 3.3: Wenn eine Generatorfunktion einen Wert zurückgibt, wird dieser Wert zum Wert für die StopIteration-Ausnahme, die ausgelöst wird. Dies kann auf verschiedene Arten erfasst werden:
Der Wert einesyield from
Ausdruck, der die einschließende Funktion impliziert, ist auch ein Generator.Wrapping einen Anruf annext()
oder.send()
in einem try / except-Block.Wenn ich jedoch einfach in einer for-Schleife über den Generator iterieren möchte - auf einfachste Weise - gibt es anscheinend keine Möglichkeit, den Wert der StopIteration-Ausnahme und damit den Rückgabewert zu erfassen. Ich verwende ein einfaches Beispiel, in dem der Generator Werte ausgibt und am Ende eine Art Zusammenfassung zurückgibt (laufende Summen, Durchschnittswerte, Timing-Statistiken usw.).
for i in produce_values():
do_something(i)
values_summary = ....??
ine Möglichkeit besteht darin, die Schleife selbst zu handhaben:
values_iter = produce_values()
try:
while True:
i = next(values_iter)
do_something(i)
except StopIteration as e:
values_summary = e.value
Aber dies wirft die Einfachheit der for-Schleife weg. Ich kann @ nicht verwendyield from
da dies erfordert, dass der aufrufende Code selbst ein Generator ist. Gibt es einen einfacheren Weg als die oben gezeigte roll-ones-own for-Schleife?
Combining Antworten von @Chad S. und @KT, die einfachste scheint meine Generatorfunktion mit dem Iterator-Protokoll in eine Klasse zu verwandeln:
class ValueGenerator():
def __iter__(self):
yield 1
yield 2
# and so on
self.summary = {...}
vg = ValueGenerator()
for i in vg:
do_something(i)
values_summary = vg.summary
Und @Ferdinand Beyers Antwort ist am einfachsten, wenn ich den Wertproduzenten nicht umgestalten kann.