War die Idee mit Iteratoren/Generatoren wirklich so super?
Anfangs war ich total begeistert von Iteratoren und Generatoren. Die Begeisterung ist nicht mehr vorhanden, schließlich ist es nichts Neues und darum auch nichts Spannendes mehr. Wenn ich zum Debugging etwas untersuchen will, und dann das hier finde: <generator object get_foo_bars at 0x7f1d3bb416e0> ... Dann ist ein weiterer "Edit, Compile, Run Cycle" nötig. Dieser "Cycle" geht in Python schnell, aber trotzdem nervt es ein klitzekleinesbischen. Ich frage mich: Bringt der Einsatz von Iteratoren und Generatoren wirklich so viel? Sicherlich gibt es extreme Beispiele bei denen die Datenmenge nicht in den Hauptspeicher passen würde. Aber solche Datenmengen habe ich im PostgreSQL, und ich mache auch Schleifchen über alle Daten in der DB :-) Wie seht ihr das? Gruß, Thomas -- Thomas Guettler http://www.thomas-guettler.de/
Thomas Güttler schrieb am 25.07.2017 um 10:14:
Ich frage mich: Bringt der Einsatz von Iteratoren und Generatoren wirklich so viel?
Sicherlich gibt es extreme Beispiele bei denen die Datenmenge nicht in den Hauptspeicher passen würde.
Aber solche Datenmengen habe ich im PostgreSQL, und ich mache auch Schleifchen über alle Daten in der DB :-)
Wie seht ihr das?
Hauptspeicherengpässe sind das eine, aber auch bei nichtüberfließenden Datenmengen können Generatoren deutlich schneller sein. Ihr Vorteil liegt vor Allem in der effizienten Nutzung von Resourcen wenn ein Datenelement nach dem anderen komplett (oder zumindest weitreichend) verarbeitet werden kann, anstatt erst alle Elemente einmal durch die CPU zu ziehen, und dann nochmal und nochmal. Und vielleicht nochmal. Je nach Komplexität der Verarbeitung und dem Verhältnis von Einzelelementgröße zu Gesamtdatengröße kann der Unterschied durchaus frappierend sein. Obwohl es natürlich auch Fälle gibt, in denen Generatoren den Code langsamer machen, z.B. weil das einzelne Durchreichen der Daten ja auch zur Laufzeit beiträgt. Na ja, und ich finde es irgendwie auch generell schwer zu verargumentieren, dass Daten komplett im Speicher landen müssen, wenn sie auch wesentlich speichersparender verarbeitet werden können (zumindest bei ähnlicher Laufzeit, also insbesondere bei Dateiverarbeitung, Datenbankabfragen, I/O halt). Meistens ist mein Code ja zur Laufzeit nicht auf der grünen Wiese unterwegs. Stefan
On 25. Jul 2017, at 10:14, Thomas Güttler <guettliml@thomas-guettler.de> wrote:
Anfangs war ich total begeistert von Iteratoren und Generatoren.
Die Begeisterung ist nicht mehr vorhanden, schließlich ist es nichts Neues und darum auch nichts Spannendes mehr.
Wenn ich zum Debugging etwas untersuchen will, und dann das hier finde:
<generator object get_foo_bars at 0x7f1d3bb416e0>
... Dann ist ein weiterer "Edit, Compile, Run Cycle" nötig.
Dieser "Cycle" geht in Python schnell, aber trotzdem nervt es ein klitzekleinesbischen.
Ich frage mich: Bringt der Einsatz von Iteratoren und Generatoren wirklich so viel?
Sicherlich gibt es extreme Beispiele bei denen die Datenmenge nicht in den Hauptspeicher passen würde.
Aber solche Datenmengen habe ich im PostgreSQL, und ich mache auch Schleifchen über alle Daten in der DB :-)
Wie seht ihr das?
Es geht nicht nur um Datenmengen, sondern auch um Algorithmen. Wenn ich eine rekursive Datenstruktur dank eines Generators traversieren kann, ohne dabei gleich die Prozessierung reinzuwurschteln, dann ist das architektonisch ein Gewinn. Natuerlich kann man das auch irgendwie anders machen, mit callbacks oder Visitor-Pattern, aber das ist halt knoedelig. Ausserdem verstehe ich dein Argument nicht. Wenn ich debugge, benutze ich PDB. Und wenn ich einen Generator habe, dann kann ich ja nun auch in dessen Ausfuehrung einspringen. Siehe unten. Du kannst ja auch keinen Breakpoint in eine List-Comprehension setzen, machst du deswegen auch keine? Und last but not least glaubst du nur, dass du schleifen machst in der DB. Im Zweifel arbeitet die nur auf Index-Strukturen etc, und wenn du rausfinden willst, warum der Execution-Planer einen full table scan macht, obwohl doch eigentlich der Index genutzt werden sollte, dann stehst du vor einer noch schwaerzeren Box als deinem Generator. Diez #!/usr/bin/env python3 def bar(): for i in range(100): yield i def main(): import pdb; pdb.set_trace() for foo in bar(): print(foo) if __name__ == '__main__': main()
Am 25.07.2017 um 10:49 schrieb Diez B. Roggisch: ...
Und last but not least glaubst du nur, dass du schleifen machst in der DB. Im Zweifel arbeitet die nur auf Index-Strukturen etc, und wenn du rausfinden willst, warum der Execution-Planer einen full table scan macht, obwohl doch eigentlich der Index genutzt werden sollte, dann stehst du vor einer noch schwaerzeren Box als deinem Generator.
Wenn es in PostgreSQL zu viele Sequence-Scans gibt, dann kann man das relativ leicht über Monitoring oder ähnliches feststellen. Ich stehe da nicht vor einer schwarzen Box. Gruß, Thomas -- Thomas Guettler http://www.thomas-guettler.de/
Am 25.07.2017 um 10:49 schrieb Diez B. Roggisch:
On 25. Jul 2017, at 10:14, Thomas Güttler <guettliml@thomas-guettler.de> wrote:
Anfangs war ich total begeistert von Iteratoren und Generatoren.
Die Begeisterung ist nicht mehr vorhanden, schließlich ist es nichts Neues und darum auch nichts Spannendes mehr.
Wenn ich zum Debugging etwas untersuchen will, und dann das hier finde:
<generator object get_foo_bars at 0x7f1d3bb416e0>
... Dann ist ein weiterer "Edit, Compile, Run Cycle" nötig.
Dieser "Cycle" geht in Python schnell, aber trotzdem nervt es ein klitzekleinesbischen.
Ich frage mich: Bringt der Einsatz von Iteratoren und Generatoren wirklich so viel?
Sicherlich gibt es extreme Beispiele bei denen die Datenmenge nicht in den Hauptspeicher passen würde.
Aber solche Datenmengen habe ich im PostgreSQL, und ich mache auch Schleifchen über alle Daten in der DB :-)
Wie seht ihr das?
Es geht nicht nur um Datenmengen, sondern auch um Algorithmen. Wenn ich eine rekursive Datenstruktur dank eines Generators traversieren kann, ohne dabei gleich die Prozessierung reinzuwurschteln, dann ist das architektonisch ein Gewinn. Natuerlich kann man das auch irgendwie anders machen, mit callbacks oder Visitor-Pattern, aber das ist halt knoedelig.
Ich sage ja nicht, dass Generatoren immer schlecht sind. Besser als callbacks ist es sicherlich. Gruß, Thomas -- Thomas Guettler http://www.thomas-guettler.de/
Wenn ich zum Debugging etwas untersuchen will, und dann das hier finde: <generator object get_foo_bars at 0x7f1d3bb416e0> ... Dann ist ein weiterer "Edit, Compile, Run Cycle" nötig. Dieser "Cycle" geht in Python schnell, aber trotzdem nervt es ein klitzekleinesbischen.
Jepp, es ist einfacher, wirklich die Materialisierte Liste zu
durchbrömmeln. Nicht ohne Grund ist Excel das um Größenordnungen häufiger eingesetzt Datenanalyse-Tool verglichen mit Pandas und ähnlichen.
Ich frage mich: Bringt der Einsatz von Iteratoren und Generatoren wirklich so viel? Sicherlich gibt es extreme Beispiele bei denen die Datenmenge nicht in den Hauptspeicher passen würde.
der heutige "Hauptspeicher" ist die Festplatte von früher. Die Musik spielt im Prozessor-Cache, sowie im L2 und im L3 Cache. Hier ist bei Iteratoren die Wahrscheinlichkeit, dass kein Cache-Trashing stattfindet, DEUTLICH höher.
Aber solche Datenmengen habe ich im PostgreSQL, und ich mache auch Schleifchen über alle Daten in der DB :-)
PostgreSQL ist immer eine gute Entscheidung, sagt der von der
PostgreSQL-Support und Development Firma :) Anywho: ich finde, das Arbeiten mit Iteratoren + Generatoren ist gut für das Gehirn. Die Programmiererin lernt in Transformationen von Datenströmen zu denken. Ja, ein paar Gigabyte kann man locker in den Hauptspeicher stecken, und dann hinreichend schnell zugreifen. Auf der anderen Seite haben wir immer mehr Daten, die besser im "Stream" verarbeitet werden - seien es Sensordaten aus den neuen Buzz-Themen IoT und Industrie 4.0; seien es lustige Videos. Iteratoren + Generatoren schulen in einer eher deklarativen Beschreibung des Lösungsraums - und das hilft dann auch beim SQL schreiben. Gruß Harald -- GHUM GmbH Harald Armin Massa Spielberger Straße 49 70435 Stuttgart 0173/9409607 <0173%209409607> Amtsgericht Stuttgart, HRB 734971
Neben den anderen schon angesprochenen sinnvollen Anwendungsfällen, kann man mit Generatoren jede Menge lustige Sachen bauen, die in der Regel aber in komplexeren Frameworks passieren. Hier mal kurz mein Lieblingsbeispiel, das ich sehr oft mit sehr guten Erfahrungen nutze: Um Daten zu transformieren, implementieren wir "worker", die Ergebnisse zu einem Dokument berechnen. D.h. wir haben Listen von Dokument in der Art: { 'id': 123, 'title': 'xyz', 'abstract': 'mehr text' } Die Transformationen sind Funktionen der Art: def just_do_it(doc): return mache_etwas_tolles_mit(doc['title']) Und dann eben: results = [just_do_it(d) for d in docs] Soweit alles super simpel. Aber was machst du, wenn mache_etwas_tolles ein setup und teardown braucht? Z.B. das Öffnen einer Datenbankverbindung? Postgres ist ja immer eine gute Idee! ;-) Die offensichtliche Lösung sind Objekte, Basisklassen, ... Ja das geht, bläht den Code aber auf und erzeugt "Rauschen", das ich nicht mag. Wir machen das so: def worker_factory(): # hier steht der setup code con = open_connection() def worker(doc): return mache_etwas(doc, con) yield worker # teardown code con.close() Ich mag es sehr, daß der zusammengehörende Code schön kompakt an einer Stelle steht. Niemand kann unnötige Objekthierarchien einführen, ... Zieht man jetzt noch in Betracht, daß ja auch yield ein Ergebnis zurück liefern kann, das von außen via next mitgegeben wird, kann man Abläufe bauen, die du anders sicher nicht hinbekommst. Ob du das willst, ist natürlich eine andere Fragen. Aber bitte laß mir diese Option! ;-) Grüße, Achim On Tuesday, 25 July, 2017 10:14 AM, Thomas Güttler wrote:
Anfangs war ich total begeistert von Iteratoren und Generatoren.
Die Begeisterung ist nicht mehr vorhanden, schließlich ist es nichts Neues und darum auch nichts Spannendes mehr.
Wenn ich zum Debugging etwas untersuchen will, und dann das hier finde:
<generator object get_foo_bars at 0x7f1d3bb416e0>
... Dann ist ein weiterer "Edit, Compile, Run Cycle" nötig.
Dieser "Cycle" geht in Python schnell, aber trotzdem nervt es ein klitzekleinesbischen.
Ich frage mich: Bringt der Einsatz von Iteratoren und Generatoren wirklich so viel?
Sicherlich gibt es extreme Beispiele bei denen die Datenmenge nicht in den Hauptspeicher passen würde.
Aber solche Datenmengen habe ich im PostgreSQL, und ich mache auch Schleifchen über alle Daten in der DB :-)
Wie seht ihr das?
Gruß, Thomas
Achim Domma schrieb am 25.07.2017 um 11:35:
def worker_factory(): # hier steht der setup code con = open_connection()
def worker(doc): return mache_etwas(doc, con) yield worker
# teardown code con.close()
Und wenn du daran jetzt noch einen Dekorator "@contextlib.contextmanager" setzt, dann wird das Ganze auch noch so richtig sauber in with-Blöcken nutzbar. Stefan
On 25.07.2017 10:14, Thomas Güttler wrote:
Anfangs war ich total begeistert von Iteratoren und Generatoren.
Die Begeisterung ist nicht mehr vorhanden, schließlich ist es nichts Neues und darum auch nichts Spannendes mehr.
Wenn ich zum Debugging etwas untersuchen will, und dann das hier finde:
<generator object get_foo_bars at 0x7f1d3bb416e0>
... Dann ist ein weiterer "Edit, Compile, Run Cycle" nötig.
Dieser "Cycle" geht in Python schnell, aber trotzdem nervt es ein klitzekleinesbischen.
Ich frage mich: Bringt der Einsatz von Iteratoren und Generatoren wirklich so viel?
Sicherlich gibt es extreme Beispiele bei denen die Datenmenge nicht in den Hauptspeicher passen würde.
Aber solche Datenmengen habe ich im PostgreSQL, und ich mache auch Schleifchen über alle Daten in der DB :-)
Wie seht ihr das?
Gruß, Thomas
Generatoren sind (neben den schon erwähnten Fällen) dann nützlich wenn man mit einem (potentiell unendlichem) Stream von Daten arbeiten muss. vg, Johannes
Am 27.07.2017 um 09:10 schrieb Johannes:
Generatoren sind (neben den schon erwähnten Fällen) dann nützlich wenn man mit einem (potentiell unendlichem) Stream von Daten arbeiten muss.
Ja, da hast du Recht. Kompliziert wird es bloß wenn man nur wenige Einträge in der Iterator hat und zweimal iterieren möchte. Das kommt bei mir häufiger vor als riesige Datenmengen. Gruß, Thomas -- Thomas Guettler http://www.thomas-guettler.de/
participants (6)
-
Achim Domma
-
Diez B. Roggisch
-
Johannes
-
Massa, Harald Armin
-
Stefan Behnel
-
Thomas Güttler