Führt Sie durch eine detaillierte Erklärung der Verwendung des PHP-Generators

藏色散人
Freigeben: 2023-04-09 16:48:01
nach vorne
4138 Leute haben es durchsucht

Erfahren Sie, wie Sie PHP-Generatoren verwenden

Was ist ein Generator?

Wenn man sich den ausgefallenen Namen anhört, fühlt es sich an wie eine Funktion zum Erstellen von etwas. Tatsächlich ist der Generator ein Iterator für die Iteration. Es bietet eine einfachere Möglichkeit, eine einfache Objektiteration zu implementieren, verglichen mit der Definition einer Klasse zur Implementierung der Iterator-Schnittstelle, wodurch der Leistungsaufwand und die Komplexität erheblich reduziert werden.

Empfohlen: „PHP-Video-Tutorial

Ich sage schon seit langem, dass es intuitiver ist, sich den Code direkt anzuschauen.

function test1()
{
    for ($i = 0; $i < 3; $i++) {
        yield $i + 1;
    }
    yield 1000;
    yield 1001;
}
foreach (test1() as $t) {
    echo $t, PHP_EOL;
}
// 1
// 2
// 3
// 1000
// 1001
Nach dem Login kopieren

Es ist so ein einfacher Code. Erstens muss der Generator in der Methode enthalten sein und das Schlüsselwort yield verwenden. Zweitens kann jeder Ertrag als Rückgabe betrachtet werden. Wenn die äußere Schleife verwendet wird, wird jeweils der Rückgabewert eines Ertrags verwendet. In diesem Beispiel gibt die Schleife dreimal die drei Zahlen 1, 2 und 3 zurück. Schreiben Sie dann zwei weitere Yield-Zeilen außerhalb der Schleife, um 1000 bzw. 1001 auszugeben. Daher gibt die äußere foreach-Schleife insgesamt fünf Mal aus.

Es ist erstaunlich, es ist offensichtlich eine Methode, warum kann sie in einer Schleife ausgeführt werden und es ist immer noch ein sehr seltsames Format für die Rückgabe des Schleifenkörpers. Drucken wir diese test()-Methode direkt aus, um zu sehen, was gedruckt wird:

// 是一个生成器对象
var_dump(test1());
// Generator Object
// (
// )
Nach dem Login kopieren

Wenn yield zur Rückgabe von Inhalten verwendet wird, wird ein Generator-Objekt zurückgegeben. Dieses Objekt wird als Generatorobjekt bezeichnet. Es kann nicht direkt von new instanziiert werden und kann nur über die Generatorfunktion zurückgegeben werden. Diese Klasse enthält Methoden wie current () und key (). Das Wichtigste ist, dass diese Klasse die Iterator-Schnittstelle implementiert, es sich also um eine spezielle Iteratorklasse handelt.

Generator implements Iterator {
    /* 方法 */
    public current ( void ) : mixed
    public key ( void ) : mixed
    public next ( void ) : void
    public rewind ( void ) : void
    public send ( mixed $value ) : mixed
    public throw ( Exception $exception ) : void
    public valid ( void ) : bool
    public __wakeup ( void ) : void
}
Nach dem Login kopieren

Wofür wird der Generator verwendet?

Ich arbeite schon lange daran. Ist es nicht nur ein Iterator? Warum sollte man sich diese Mühe machen? Wäre es nicht besser, einfach einen Iterator zu verwenden oder direkt ein Array in der Methode zurückzugeben? Ja, unter normalen Umständen ist es eigentlich nicht so störend, aber wenn die Datenmenge besonders groß ist, kann dieser Generator seine starke Leistung entfalten. Der leistungsstärkste Teil des Generators besteht darin, dass zum Speichern dieser Datenreihe kein Array oder eine andere Datenstruktur erforderlich ist. Jede Iteration wird dynamisch zurückgegeben, wenn der Code ausgeführt wird, um zu ergeben. Daher kann der Generator erheblich Speicher sparen.

// 内存占用测试
$start_time = microtime(true);
function test2($clear = false)
{
    $arr = [];
    if($clear){
        $arr = null;
        return;
    }
    for ($i = 0; $i < 1000000; $i++) {
        $arr[] = $i + 1;
    }
    return $arr;
}
$array = test2();
foreach ($array as $val) {
}
$end_time = microtime(true);
echo "time: ", bcsub($end_time, $start_time, 4), PHP_EOL;
echo "memory (byte): ", memory_get_usage(true), PHP_EOL;
// time: 0.0513
// memory (byte): 35655680
$start_time = microtime(true);
function test3()
{
    for ($i = 0; $i < 1000000; $i++) {
        yield $i + 1;
    }
}
$array = test3();
foreach ($array as $val) {
}
$end_time = microtime(true);
echo "time: ", bcsub($end_time, $start_time, 4), PHP_EOL;
echo "memory (byte): ", memory_get_usage(true), PHP_EOL;
// time: 0.0517
// memory (byte): 2097152
Nach dem Login kopieren

Der obige Code erhält das Ergebnis einfach nach 1.000.000 Schleifen, kann aber auch intuitiv gesehen werden. Die Version mit Generator verbraucht nur 2 MB Speicher, während die Version ohne Generator 35 MB Speicher verbraucht, was mehr als dem Zehnfachen des Unterschieds entspricht. Je größer der Unterschied, desto offensichtlicher ist der Unterschied. Daher sagen einige Experten, dass der Generator die am meisten unterschätzte Funktion in PHP ist.

Anwendungen von Generatoren

Als nächstes werfen wir einen Blick auf einige grundlegende Anwendungsmethoden von Generatoren.

Einen Nullwert zurückgeben und unterbrechen

Natürlich kann der Generator auch einen Nullwert zurückgeben, nur eine Rückgabe ohne Wert kann einen Nullwert zurückgeben. Die direkte Verwendung von return; in einer Methode kann auch dazu verwendet werden, die weitere Ausführung des Generators zu unterbrechen. Im folgenden Code geben wir einen Nullwert zurück, wenn $i = 4;, d. h. 5 wird nicht ausgegeben (da wir $i + 1 zurückgeben). Wenn dann $i == 7

​​​​​​verwenden Sie return;, um die weitere Ausführung des Generators zu unterbrechen, d. h. die Schleife gibt nur bis 7 aus und endet.

// 返回空值以及中断
function test4()
{
    for ($i = 0; $i < 10; $i++) {
        if ($i == 4) {
            yield; // 返回null值
        }
        if ($i == 7) {
            return; // 中断生成器执行
        }
        yield $i + 1;
    }
}
foreach (test4() as $t) {
    echo $t, PHP_EOL;
}
// 1
// 2
// 3
// 4
// 5
// 6
// 7
Nach dem Login kopieren

Schlüssel-Wert-Paare zurückgeben

Seien Sie nicht überrascht, der Generator kann wirklich ein durchquerbares Objekt in Form von Schlüssel-Wert-Paaren zur Verwendung durch foreach zurückgeben, und die Syntax ist sehr leicht zu merken: yield key => value; Ist es dasselbe wie ein Array? Die Definitionsform der Elemente ist genau die gleiche, was sehr intuitiv und leicht zu verstehen ist.

function test5()
{
    for ($i = 0; $i < 10; $i++) {
        yield &#39;key.&#39; . $i => $i + 1;
    }
}
foreach (test5() as $k=>$t) {
    echo $k . &#39;:&#39; . $t, PHP_EOL;
}
// key.0:1
// key.1:2
// key.2:3
// key.3:4
// key.4:5
// key.5:6
// key.6:7
// key.7:8
// key.8:9
// key.9:10
Nach dem Login kopieren

Externe Datenübergabe

Wir können einen Wert über die Methode Generator::send an den Generator übergeben. Der übergebene Wert wird als Rückgabewert des aktuellen Ertrags des Generators behandelt. Anschließend können wir auf der Grundlage dieses Werts einige Urteile fällen, z. B. die Unterbrechung der Ausführung des Generators basierend auf externen Bedingungen.

function test6()
{
    for ($i = 0; $i < 10; $i++) {
        // 正常获取循环值,当外部send过来值后,yield获取到的就是外部传来的值了
        $data = (yield $i + 1);
        if($data == &#39;stop&#39;){
            return;
        }
    }
}
$t6 = test6();
foreach($t6 as $t){
    if($t == 3){
        $t6->send(&#39;stop&#39;);
    }
    echo $t, PHP_EOL;
}
// 1
// 2
// 3
Nach dem Login kopieren

Der obige Code ist möglicherweise verwirrend zu verstehen, aber denken Sie einfach an die Zeile im Kommentar (erhalten Sie den Schleifenwert normal, wenn der Wert von außen gesendet wird, erhält die Ausbeute den Wert von außen). Darüber hinaus müssen Variablen in Klammern eingeschlossen werden, um den Ertragswert zu erhalten.

Ausbeute aus der Syntax

Ausbeute aus der Syntax bezieht sich eigentlich darauf, Daten einzeln von einem anderen iterierbaren Objekt zu erhalten und eine Generatorrückgabe zu bilden. Schauen Sie sich einfach den Code an.

function test7()
{
    yield from [1, 2, 3, 4];
    yield from new ArrayIterator([5, 6]);
    yield from test1();
}
foreach (test7() as $t) {
    echo &#39;test7:&#39;, $t, PHP_EOL;
}
// test7:1
// test7:2
// test7:3
// test7:4
// test7:5
// test7:6
// test7:1
// test7:2
// test7:3
// test7:1000
Nach dem Login kopieren

In der test7()-Methode verwenden wir yield from, um Daten von einem gewöhnlichen Array, einem Iteratorobjekt bzw. einem anderen Generator abzurufen und sie als Inhalt des aktuellen Generators zurückzugeben.

Kleine Überraschung

Kann der Generator mithilfe der Zählung die Menge ermitteln?

Leider kann der Generator die Anzahl nicht verwenden, um seine Menge zu ermitteln.

$c = count(test1()); // Warning: count(): Parameter must be an array or an object that implements Countable
// echo $c, PHP_EOL;
Nach dem Login kopieren

Wenn Sie count verwenden, um die Anzahl der Generatoren zu ermitteln, wird direkt eine Warnung ausgegeben. Bei der direkten Ausgabe wird aufgrund der Eigenschaften von count immer 1 angezeigt (bei erzwungener Ausgabe in ein Array wird 1 angezeigt).

Verwenden Sie den Generator, um die Fibonacci-Folge zu erhalten

// 利用生成器生成斐波那契数列
function fibonacci($item)
{
    $a = 0;
    $b = 1;
    for ($i = 0; $i < $item; $i++) {
        yield $a;
        $a = $b - $a;
        $b = $a + $b;
    }
}
$fibo = fibonacci(10);
foreach ($fibo as $value) {
    echo "$value\n";
}
Nach dem Login kopieren

Dieser Code erfordert keine große Erklärung, es ist ein sehr intuitiver Code.

Zusammenfassung

Der Generator ist definitiv ein verborgener Schatz in PHP, nicht nur wegen der Speicherersparnis, sondern die Syntax ist tatsächlich sehr prägnant und klar. Wir müssen kein zusätzliches Array innerhalb der Methode definieren, um den Rückgabewert zu speichern, wir können einfach nacheinander yield und return ausführen. Es lohnt sich auf jeden Fall, es in tatsächlichen Projekten auszuprobieren, aber vergessen Sie nicht, es mit Ihren Freunden zu teilen, nachdem Sie es ausprobiert haben. Die meisten Leute haben diese Funktion vielleicht noch nie kennengelernt! !

Testcode: https://github.com/zhangyue0503/dev-blog/blob/master/php/202002/source/%E5%AD%A6%E4%B9%A0PHP%E7%94%9F%E6% 88%90%E5%99%A8%E7%9A%84%E4%BD%BF%E7%94%A8.php

Referenzdokumentation: https://www.php.net/manual/zh/sprache. generators.overview.php https://www.php.net/manual/zh/class.generator.php

Das obige ist der detaillierte Inhalt vonFührt Sie durch eine detaillierte Erklärung der Verwendung des PHP-Generators. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:zhihu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!