Sollte ich Python-Generatoren Listen vorziehen?

8

Python-Iteratoren können sehr speichereffizient sein. Sollte ich immer lieber Generatoren als nur Listen verwenden? In welchen Situationen sollte ich ein einfaches Array bevorzugen?

Zum Beispiel stattdessen:

emails = [user.email for user in users]

soll ich das vorziehen?:

emails = (user.email for user in users)

Hinweis : Ich meine "Generatoren", nicht "Iteratoren".

Nicholaides
quelle
Unklar, welche Hilfe Sie brauchen . Bitte klären Sie Ihr spezifisches Problem oder geben Sie zusätzliche Details an, um genau das hervorzuheben, was Sie benötigen. Wie derzeit geschrieben, ist es schwer zu sagen, welches Problem Sie lösen möchten oder welcher Aspekt Ihres Ansatzes korrigiert oder erklärt werden muss. Weitere Informationen zur Klärung dieser Frage finden Sie auf der Seite Fragen.
Mücke
@gnat würde die Frage umformuliert als "Wann sollte ich Iteratoren oder Listen in Python verwenden?" in Ordnung sein?
Florian Margaine
@FlorianMargaine, die es in Gefahr bringen würde, als zu breit geschlossen zu werden, fürchte ich
Mücke
2
@FlorianMargaine Das wäre ein guter Anfang, aber es ist immer noch eine schwache Frage. Wo ist die Forschung des Autors? Sicher kann er sich ein paar Unterschiede vorstellen. Es ist nicht so toll, nach allen Situationen zu fragen, in denen Sie die eine oder andere verwenden möchten.
Doval
2
+1 Es mag eine etwas unklare Frage sein, aber wenn Sie gerade erst lernen, diese Strukturen zu verwenden, werden Ihre Fragen vage formuliert und formuliert. Ich habe viel aus den Antworten gelernt.
Racheet

Antworten:

7

Der Hauptnachteil von Generatoren besteht darin, dass sie nur in eine Richtung gefahren werden können. Es gibt kein Zurück zu einem vorherigen Wert. Sie können sie auch nicht teilen. Es gibt viele Fälle, in denen dies leicht erklärt werden kann oder sogar vorzuziehen ist, aber es gibt auch viele Fälle, in denen dies nicht der Fall ist. Zum Beispiel sortieren.

Aus diesem Grund werden häufig Generatoren für die anfänglichen Verarbeitungsphasen einer großen Datenmenge verwendet. Sobald diese in eine Teilmenge gefiltert und in ein schönes Format abgebildet wurden, werden sie in eine langlebige konkrete Datenstruktur für übertragen weitere Verwendung. Auf diese Weise geben Sie nicht die Speicherzuweisung, Cache-Fehler und Speicherbereinigungskosten für große Zwischen-Arrays aus, die Sie sofort wegwerfen.

Karl Bielefeldt
quelle
3

Sie haben Iteratoren mit Generatoren verwechselt.

Ihr erstes Beispiel ist ein Listeniteratorausdruck, während das zweite ein Generatorausdruck ist. Der Hauptunterschied besteht darin, dass der Generator jedes Mitglied der angegebenen Sammlung eher träge (nach Bedarf) als eifrig (sofort, ob benötigt oder nicht) erstellt. Sie können Ihre eigenen Generatoren definieren, indem Sie Yield anstelle von Return verwenden.

Was die Verwendung betrifft, möchten Sie einen Iterator, wenn Sie die Liste (oder das Wörterbuch oder was auch immer) für etwas an und für sich benötigen. Sie würden einen Generator verwenden, wenn die Sammlung zum Endprodukt gehört. Beispielsweise können Sie einen Generator verwenden, um eine Liste von Zahlen abzurufen, die einige Kriterien von anderen Kriterien erfüllen. Die ursprüngliche Liste interessiert Sie nicht, nur die Mitglieder, die den Kriterien entsprechen. Sie verwenden also einen Generator, um nur diese Zahlen zu erhalten.

Ein konkreteres Beispiel wäre das Finden der Winkel von Dreiecken, deren Seiten eine bestimmte Länge haben. Wir wollen nicht alle armen, deformierten, gescheiterten Dreiecke, sondern nur die starken, gesunden, erfolgreichen Dreiecke. Also würden wir einen Generator verwenden.

Dieser Beitrag zum Stapelüberlauf wird ausführlicher beschrieben.

Weltingenieur
quelle