Was ist yield
?
Das yield
Schlüsselwort gibt Daten von einer Generatorfunktion zurück:
Das Herzstück einer Generatorfunktion ist das Yield-Schlüsselwort. In seiner einfachsten Form ähnelt eine Yield-Anweisung einer Return-Anweisung, mit der Ausnahme, dass Yield nicht die Ausführung der Funktion stoppt und zurückgibt, sondern stattdessen einen Wert für die Code-Schleife über den Generator bereitstellt und die Ausführung der Generatorfunktion anhält.
Was ist eine Generatorfunktion?
Eine Generatorfunktion ist effektiv eine kompaktere und effizientere Möglichkeit, einen Iterator zu schreiben . Sie können eine Funktion (Ihre xrange
) definieren, die Werte berechnet und zurückgibt , während Sie sie durchlaufen :
foreach (xrange(1, 10) as $key => $value) {
echo "$key => $value", PHP_EOL;
}
Dies würde die folgende Ausgabe erzeugen:
0 => 1
1 => 2
…
9 => 10
Sie können auch die Kontrolle $key
in dem foreach
durch den Einsatz
yield $someKey => $someValue;
In der Generatorfunktion, $someKey
ist alles , was Sie erscheinen möchten $key
und $someValue
in dem Wert sein $val
. Im Beispiel der Frage ist das$i
.
Was ist der Unterschied zu normalen Funktionen?
Jetzt fragen Sie sich vielleicht, warum wir nicht einfach die native Funktion von PHP range
verwenden , um diese Ausgabe zu erzielen. Und richtig bist du. Die Ausgabe wäre die gleiche. Der Unterschied ist, wie wir dorthin gekommen sind.
Wenn wir range
PHP verwenden, wird es ausgeführt, das gesamte Array von Zahlen im Speicher und return
das gesamte Array in der foreach
Schleife erstellt, die dann darüber hinweggeht und die Werte ausgibt. Mit anderen Worten, das foreach
wird auf dem Array selbst arbeiten. Die range
Funktion und das foreach
einzige "Gespräch" einmal. Stellen Sie sich vor, Sie bekommen ein Paket per Post. Der Zusteller wird Ihnen das Paket geben und gehen. Und dann packen Sie das gesamte Paket aus und nehmen alles heraus, was sich darin befindet.
Wenn wir die Generatorfunktion verwenden, tritt PHP in die Funktion ein und führt sie aus, bis sie entweder das Ende oder ein yield
Schlüsselwort erreicht. Wenn es auf a trifft yield
, gibt es den zu diesem Zeitpunkt angegebenen Wert an die äußere Schleife zurück. Dann geht es zurück in die Generatorfunktion und setzt dort fort, wo es nachgegeben hat. Da Sie xrange
eine for
Schleife halten, wird diese ausgeführt und gibt nach, bis sie $max
erreicht wurde. Stellen Sie sich das wie foreach
den Generator vor, der Tischtennis spielt.
Warum brauche ich das?
Offensichtlich können Generatoren verwendet werden, um Speichergrenzen zu umgehen. Abhängig von Ihrer Umgebung kann das Ausführen eines range(1, 1000000)
Skripts Ihr Skript beschädigen, während das gleiche mit einem Generator einwandfrei funktioniert. Oder wie Wikipedia es ausdrückt:
Da Generatoren ihre Ertragswerte nur bei Bedarf berechnen, sind sie nützlich, um Sequenzen darzustellen, deren Berechnung teuer oder unmöglich wäre. Dazu gehören zB unendliche Sequenzen und Live-Datenströme.
Generatoren sollen auch ziemlich schnell sein. Aber denken Sie daran, dass wir, wenn wir schnell sprechen, normalerweise in sehr geringer Anzahl sprechen. Bevor Sie jetzt loslegen und Ihren gesamten Code ändern, um Generatoren zu verwenden, führen Sie einen Benchmark durch, um festzustellen, wo dies sinnvoll ist.
Ein weiterer Anwendungsfall für Generatoren sind asynchrone Coroutinen. Das yield
Schlüsselwort gibt nicht nur Werte zurück, sondern akzeptiert sie auch. Einzelheiten dazu finden Sie in den beiden unten verlinkten ausgezeichneten Blog-Posts.
Seit wann kann ich verwenden yield
?
Generatoren wurden in PHP 5.5 eingeführt . Der Versuch, yield
vor dieser Version zu verwenden , führt je nach dem Code, der auf das Schlüsselwort folgt, zu verschiedenen Analysefehlern. Wenn Sie also einen Analysefehler von diesem Code erhalten, aktualisieren Sie Ihr PHP.
Quellen und weiterführende Literatur:
yeild
eine Lösung wie diese bietetreturn range(1,100000000)
undfor ($i=0; $i<100000000; $i++) yield $i
Diese Funktion verwendet Ausbeute:
ist fast das gleiche wie dieses ohne:
Der einzige Unterschied besteht darin, dass
a()
ein Generator undb()
nur ein einfaches Array zurückgegeben werden. Sie können auf beiden iterieren.Außerdem weist der erste kein vollständiges Array zu und ist daher weniger speicherintensiv.
quelle
einfaches Beispiel
Ausgabe
fortgeschrittenes Beispiel
Ausgabe
quelle
yield
Schlüsselwort dient zur Definition von "Generatoren" in PHP 5.5. Ok, was ist dann ein Generator ?Von php.net:
Von diesem Ort aus: Generatoren = Generatoren, andere Funktionen (nur einfache Funktionen) = Funktionen.
Sie sind also nützlich, wenn:
Sie müssen einfache (oder einfache) Dinge tun.
Generator ist wirklich viel einfacher als die Implementierung der Iterator-Schnittstelle. Andererseits sind Generatoren natürlich weniger funktionsfähig. vergleiche sie .
Sie müssen GROSSE Datenmengen generieren, um Speicherplatz zu sparen.
Um Speicherplatz zu sparen, können wir einfach die erforderlichen Daten über Funktionen für jede Schleifeniteration generieren und nach der Iteration Müll verwenden. Hier geht es also hauptsächlich um klaren Code und wahrscheinlich um Leistung. Sehen Sie, was für Ihre Bedürfnisse besser ist.
Sie müssen eine Sequenz generieren, die von Zwischenwerten abhängt.
Dies erweitert den vorherigen Gedanken. Generatoren können die Arbeit im Vergleich zu Funktionen erleichtern. Überprüfen Sie das Fibonacci-Beispiel und versuchen Sie, eine Sequenz ohne Generator zu erstellen. Auch Generatoren können in diesem Fall schneller arbeiten, zumindest weil Zwischenwerte in lokalen Variablen gespeichert werden.
Sie müssen die Leistung verbessern.
In einigen Fällen können sie schneller arbeiten als Funktionen (siehe vorherigen Vorteil).
quelle
Mit können
yield
Sie einfach die Haltepunkte zwischen mehreren Aufgaben in einer einzigen Funktion beschreiben. Das ist alles, es ist nichts Besonderes daran.Wenn task1 und task2 eng miteinander verbunden sind, Sie jedoch einen Haltepunkt zwischen ihnen benötigen, um etwas anderes zu tun:
Dann sind Generatoren die beste Lösung, da Sie Ihren Code nicht in viele Abschlüsse aufteilen oder mit anderem Code mischen oder Rückrufe usw. verwenden müssen. Sie müssen nur
yield
einen Haltepunkt hinzufügen, und Sie können damit fortfahren Haltepunkt, wenn Sie bereit sind.Haltepunkt ohne Generatoren hinzufügen:
Haltepunkt mit Generatoren hinzufügen
Hinweis: Es ist leicht, Fehler mit Generatoren zu machen. Schreiben Sie daher immer Unit-Tests, bevor Sie sie implementieren! note2: Die Verwendung von Generatoren in einer Endlosschleife ist wie das Schreiben eines Verschlusses mit unendlicher Länge ...
quelle
Keine der obigen Antworten zeigt ein konkretes Beispiel für die Verwendung massiver Arrays, die von nicht numerischen Elementen gefüllt werden. Hier ist ein Beispiel mit einem Array, das von
explode()
einer großen TXT-Datei generiert wurde (262 MB in meinem Anwendungsfall):Die Ausgabe war:
Vergleichen Sie das nun mit einem ähnlichen Skript unter Verwendung des
yield
Schlüsselworts:Die Ausgabe für dieses Skript war:
Die Einsparungen bei der Speichernutzung waren eindeutig beträchtlich (ΔMemoryUsage -----> ~ 270,5 MB im ersten Beispiel, ~ 450B im zweiten Beispiel).
quelle
Ein interessanter Aspekt, der hier diskutiert werden sollte, ist die Bezugnahme . Jedes Mal, wenn wir einen Parameter so ändern müssen, dass er außerhalb der Funktion wiedergegeben wird, müssen wir diesen Parameter als Referenz übergeben. Um dies auf Generatoren anzuwenden, stellen wir
&
dem Namen des Generators und der in der Iteration verwendeten Variablen einfach ein kaufmännisches Und voran:Das obige Beispiel zeigt, wie das Ändern der iterierten Werte innerhalb der
foreach
Schleife die$from
Variable innerhalb des Generators ändert . Dies liegt daran ,$from
wird durch Bezugnahme ergibt aufgrund der Et - Zeichen vor dem Generator Namen. Aus diesem Grund ist die$value
Variable innerhalb derforeach
Schleife eine Referenz auf die$from
Variable innerhalb der Generatorfunktion.quelle
Der folgende Code zeigt, wie die Verwendung eines Generators ein Ergebnis vor Abschluss zurückgibt, im Gegensatz zum herkömmlichen Ansatz ohne Generator, bei dem nach vollständiger Iteration ein vollständiges Array zurückgegeben wird. Mit dem folgenden Generator werden die Werte zurückgegeben, wenn sie bereit sind. Sie müssen nicht warten, bis ein Array vollständig gefüllt ist:
quelle