Jose: Hey Leute, willkommen zurück
und in diesem Video sprechen wir über Generatoren in Python.
Ich freue mich sehr auf diesen
Abschnitt, weil wir über einige fortgeschrittene Dinge
sprechen werden, und Generatoren sind eines dieser
Themen in Python, die in vielen Kursen
gar nicht erwähnt werden, die aber für die Leistung unerlässlich sind
und auch, weil die e-sync-Entwicklung in Python, die e-synchrone Entwicklung,
die wir später noch lernen
werden, auf diesen Generatoren aufbaut.
Wenn man die Generatoren
versteht, werden viele Dinge in Python viel klarer.
Was ist also ein Generator?
Ein Generator in Python ist eine Funktion.
Es ist eine besondere Funktion.
Sehen Sie eine Funktion, die sich den Zustand, in dem sie
sich zwischen den Ausführungen
befindet, merkt, so dass Sie die Funktion mehrmals
ausführen können und sie sich daran erinnert,
was sie bei der letzten Ausführung getan hat.
Das hört sich jetzt ziemlich seltsam an, aber ich möchte es an einem Beispiel erklären.
Stellen Sie sich vor, Sie wollen eine
Liste mit 100 Zahlen
erstellen. Ganz einfach, Sie wollen eine neue Liste mit Zahlen
von Null bis 99, ohne 100.
Sie könnten also eine Funktion wie diese erstellen.
Offensichtlich nicht mit Reichweite und so weiter, Sie wissen Reichweite.
Lassen Sie uns nicht den Bereich verwenden, sondern eine Liste von Grund auf erstellen.
Wie würden Sie es tun?
Eine gute Möglichkeit wäre, mit einer leeren Liste zu beginnen.
Nennen wir sie nums und machen sie gleich einer leeren Liste.
Und auch mit einem Index gleich Null beginnen.
Dann, solange i kleiner als 100
ist, sagen wir nums dot append i.
Sie werden also eine Null an den Anfang anhängen.
Dann erhöhst du i um eins, wodurch
es zu eins wird.
Sie werden eine anhängen, wiederholen, zwei
anhängen, dann drei und so weiter, bis Sie bei 99 angelangt sind.
Und am Ende dieser Funktion geben
Sie nums zurück, das ist Ihre Zahlenliste.
Wenn wir Hunderte von Zahlen ausdrucken und das ausführen.
Wir können sehen, dass sie
hier unsere Liste von hundert Nummern enthält.
Natürlich könnten wir dafür das Listenverständnis verwenden.
Wir könnten die Bereichsfunktion
verwenden, aber nehmen wir einmal an,
dass dies eine gute Methode ist, denn ich erkläre hier
im Wesentlichen, wie die Bereichsfunktion im Inneren funktioniert.
Wir erstellen also eine Liste,
füllen sie mit den ersten hundert Zahlen und kehren dann zurück.
Jetzt haben wir hundert Zahlen in einer Liste.
Diese gesamte Liste ist im Speicher Ihres Computers als Rückgabewert
der Funktion gespeichert.
Nun sind hundert Zahlen nicht sehr groß,
es ist eine ziemlich kleine Menge
an Platz, aber sagen wir, wir wollten 10 Millionen speichern,
eine Million ist wie hundert Zahlen, aber
es wäre so etwas wie eine Million Zahlen.
Sie würden eine Liste mit einer Million Zahlen erstellen
und sie in dieser Variablen speichern,
die in den Speicher Ihres Computers geht, und es
ist vermutlich eine größere Menge an Speicher, die sie
benötigt, weil jede dieser Zahlen einen kleinen
Teil des Speichers Ihres Computers beansprucht.
Wenn Sie 10 Millionen Zahlen wollten, dann ist es größer und so.
Nun sind 10 Millionen Zahlen kein gutes Beispiel, aber stellen
Sie sich vor, Sie haben eine sehr lange Liste von etwas.
Diese werden zum Beispiel häufig bei der
Berechnung von Primzahlen und bei Big Data und ähnlichen
Dingen verwendet, bei denen man vielleicht
manchmal große Listen von Dingen benötigt.
Daher wird ein Generator verwendet, um dieses Problem
zu umgehen, da man davon ausgeht, dass man nicht 100 Zahlen
auf einmal benötigt.
Was Sie brauchen, ist Null, damit Sie etwas damit anfangen können.
Und dann eine, damit man etwas damit machen kann.
Und dann zwei, damit man etwas damit machen kann.
Mit diesen hundert Zahlen könnten wir zum
Beispiel alle mit zwei multiplizieren und sie in einer anderen Liste speichern.
Wie würden Sie das machen?
Sie würden so etwas tun wie weniger Verständnis,
x mal zwei für x in hundert Zahlen.
Sie verwenden diese Liste, um sie
zu isolieren, und multiplizieren jede Zahl mit zwei.
Nehmen wir an, dass diese Multiplikation
mit zwei eine Operation ist, die wir mit diesen
Zahlen durchführen wollen, um etwas zu berechnen.
Ein anderes Beispiel wäre, wenn Sie eine große
Anzahl von Nutzern haben und deren Engagement berechnen wollen,
oder wie engagiert sie mit Ihrem System sind,
oder etwas Ähnliches.
Im Wesentlichen wollen Sie jedes Element
durchgehen und eine Operation durchführen.
Die Sache ist die, dass man nicht alle Elemente auf einmal braucht.
Sie brauchen sie nacheinander.
Hierfür werden also Generatoren eingesetzt.
Anstatt die gesamte Liste der Elemente zu
haben, gibt Ihnen der Generator
das erste Element der Liste,
ohne die gesamte Liste im Speicher zu speichern.
Wenn Sie den Generator das nächste Mal
aufrufen, merkt er sich das Element, das er Ihnen zuletzt gegeben
hat, und er weiß, dass er Ihnen das zweite Element geben muss.
Dann führen Sie es noch einmal aus, und Sie erhalten das dritte
Element, und so weiter.
Es speichert die Liste nie ab, sondern merkt
sich immer nur die letzte Nummer, die es Ihnen gegeben hat, um
Ihnen dann die nächste geben zu können.
Sie müssen die Funktion jedes
Mal ausführen, wenn Sie eine neue Zahl benötigen,
und deshalb heißt sie Generator, weil sie Zahlen,
Zeichenketten oder Benutzer oder was auch immer Sie generieren möchten, erzeugt.
Anstelle von "nums" würden Sie folgendermaßen vorgehen. append(i)", sagen Sie "yield
i", denn i ist die Zahl, die wir zurückgeben wollen, wir
brauchen diese nums equal eckige
Klammer nicht mehr, und wir brauchen
auch das return-Segment nicht mehr.
Diese Funktion hier wird also Generatorfunktion genannt.
Yield ist dem Return sehr ähnlich, aber es gibt Ihnen i, wenn
Sie es aufrufen, und dann merkt es sich, dass es hier ist, es ist
kurz vor Zeile fünf stehen geblieben.
Gleich
nach Zeile vier dort in der Mitte.
Wenn du die Funktion das nächste Mal aufrufst,
wird sie fortgesetzt, d.h. sie erhöht
i um eins, führt die Schleife erneut aus, gibt
eins aus und hält dann an.
Das nächste Mal, wenn du es aufrufst,
wird es weiter erhöhen ich kaufe einen
und die Schleife wiederholen und dir dann zwei geben, und dann wird es aufhören, und so weiter.
Wenn Sie keine Zahlen mehr haben,
werden Sie auch keine mehr finden.
Und dann weiß man, dass es vorbei ist.
Und wie wollen wir das machen?
Drucken wir zunächst einmal hundert Zahlen aus.
Beachten Sie, dass wir jetzt nicht mehr eine
Liste, sondern ein Generatorobjekt erhalten,
das hundert Zahlen heißt, daher der Name
unserer Funktion.
Sie gibt uns auch die Speicheradresse unseres Objekts.
Beachten Sie, dass wir eine Funktion definiert haben,
aber der Ausdruck sagt uns, dass es sich um ein Objekt handelt,
weil Python im Hintergrund erkennt,
dass Sie yield verwendet haben, dass Sie einen Generator
erzeugen, und dies in ein Python-Objekt umwandelt.
Ich werde Ihnen später erklären, wie Sie diese
Objekte ohne eine Funktion selbst herstellen können.
Speichern wir also unseren Generator in einer Variablen.
Wir werden ihn "g" nennen, das ist ein ziemlich
beliebter Name für einen Generator in einem kleinen Programm.
Wenn Sie viele Generatoren haben, müssen
Sie natürlich einen beschreibenderen Namen wählen.
Dann geben wir den nächsten Wert aus, den
der Generator uns liefern würde.
Beachten Sie, dass bei der Initialisierung eines Generators die
Funktion nicht ausgeführt wird, sondern ganz am Anfang steht, ohne
dass sie überhaupt ausgeführt wird.
Wenn Sie ihn nach dem nächsten Wert fragen, läuft
er bis zum Ertrag hoch und gibt
Ihnen den Wert, den Sie abgegeben haben.
Die Art und Weise, wie Sie nach dem nächsten
Wert fragen, ist, dass Sie die Funktion nicht noch einmal ausführen, sondern "g" sagen.
Als Nächstes folgt eine eingebaute Funktion, die sich auf die Generatoren auswirkt
und ihnen sagt, dass sie bis zum Ertrag gehen sollen.
Okay, wenn wir das ausführen, sehen Sie, dass wir Null erhalten, denn
das ist die allererste Zahl, die wir erhalten.
Jetzt hat unser Generator "g" hier in der Zeile
4 angehalten. 5 zwischen 4 und 5. Wenn wir
ihn also nach einer anderen Zahl fragen, beachten Sie, dass der Generator am Ende eines Programms
natürlich zerstört wird, d.h. wenn wir dieses
Programm noch einmal laufen lassen, wäre dies wieder
eine Null und dies wäre jetzt eine Eins.
Es merkt sich das nicht über Programmausführungen
hinweg, so funktioniert Python einfach nicht.
Jetzt können wir die erste Zahl abfragen, und
dann die nächste Zahl.
Nach der ersten Zahl wird sie zwischen
vier und fünf gestoppt.
Wenn wir next sagen, geht es weiter bis zum nächsten Yield, was bedeutet,
dass wir diese Schleife einmal wiederholen und uns einen geben.
Ja.
Ganz wichtig: Die Funktion merkt sich, wo sie aufgehört hat.
Sie können also jederzeit die Ausführung der Funktion
anhalten und dann next aufrufen, um sie fortzusetzen.
Es ist also nicht nur nützlich, um Zahlen oder ähnliches zu generieren,
sondern auch, um eine Funktion vorübergehend anzuhalten,
damit man sie jederzeit wieder ausführen
kann, indem man next aufruft.
Das macht jetzt vielleicht noch nicht
so viel Sinn, aber denken Sie daran, wenn wir es bei einer
synchronisierten Programmierung brauchen.
Und was ist mit der Bereichsfunktion?
Ich habe vorhin gesagt, dass dies im Wesentlichen
erklärt, wie die Bereichsfunktion im Inneren funktioniert, und das ist wahr, aber die
Bereichsfunktion gibt
Ihnen nicht direkt einen Generator.
Hier, lassen Sie uns etwas wie "mein
Bereichsobjekt" machen, es wird der
Bereich 10 sein.
Dies verhält sich sehr ähnlich wie ein Generator, aber wenn Sie
next von "my range object" aufrufen, erhalten Sie
eine Fehlermeldung, und sehen Sie sich das an.
Das liegt daran, dass das Range-Objekt nicht wirklich ein Generator
ist, auch wenn es sich so verhält.
Es erzeugt keine Liste und ermöglicht es Ihnen dann,
darüber zu iterieren, sondern es verhält sich auf diese Art und Weise, um effizienter
zu sein.
"Mein Bereichsobjekt", Sie erinnern
sich sicher, dass wir es schon viel
früher im Kurs ausgedruckt haben,
und wir bekamen so ein komisches Bereich-Null-Zehn-Ding.
Das ist nur die Funktion "repr", die aufgerufen wird, und wie Sie sehen
können, wenn wir das Ergebnis von "repr" ausdrucken, sehen wir
auch einen Bereich von null bis zehn.
Wir werden in ein paar Videos genau
lernen, wie wir über ein
Objekt iterieren können, damit es sich wie ein Bereichsobjekt
verhält.
Wir haben also etwas über diese Generatoren gelernt, und eine weitere
Sache, die ich noch erwähnen wollte, ist,
dass die Funktion list einen Generator in eine Liste verwandeln kann.
Wir können also eine Liste von "g" drucken.
Genau hier haben wir "next", dann wieder "next"
und dann "list" genannt.
Jetzt haben wir also Null und Eins ausgedruckt, denn das sind die beiden Dinge in
unseren "next"-Funktionen, und dann haben
wir eine Liste des Generators erstellt, aber
diese Liste geht natürlich dort weiter, wo wir aufgehört haben.
Der Generator selbst merkt sich, was
es war, also beginnt die Liste bei zwei und nicht bei null.
Es ist also sehr wichtig, dass sich die Erzeuger
daran erinnern, wo sie waren.
Wenn Sie also eine erstellen, dann ist es das im Wesentlichen von dem Moment an, in dem Sie sie benutzen,
von dem Moment an, in dem Sie "next"
aufrufen, merkt sie sich, wo sie ist, und Sie können
nicht mehr zurückgehen. Ja.
In den nächsten Videos werden wir
mehr über Generatoren erfahren.
Wir werden etwas über Generator-Klassen
lernen, wie man eine Klasse erstellen kann, die sich wie ein Generator
verhält, und wir werden auch etwas über Iteratoren und Iterables in Python
lernen, und die Bereichsziele sind ein solches
Beispiel.
Dann werden wir zu einigen
Beispielen der funktionalen Programmierung
übergehen, wie filter, map, any and all und enumerate.
Ich bin sehr gespannt auf diesen
Abschnitt und bin zuversichtlich, dass Generatoren etwas sein
werden, das Sie in Ihrer Python-Entwicklung brauchen werden,
vor allem, wenn wir im weiteren Verlauf des Kurses fortfahren.
In diesem Sinne, wir sehen uns beim nächsten Video wieder.