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?

Antwortzusammenfassung

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.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage