Heim > Backend-Entwicklung > PHP-Tutorial > Verstehen der Verwendung des PHP-Yield-Coroutine-Generators

Verstehen der Verwendung des PHP-Yield-Coroutine-Generators

coldplay.xixi
Freigeben: 2023-04-09 06:36:02
nach vorne
2848 Leute haben es durchsucht

Verstehen der Verwendung des PHP-Yield-Coroutine-Generators

Geschrieben vor

In diesem Artikel möchte ich mit Ihnen die Verwendung von PHP yield in Generatoren ohne foreach besprechen. for, while Die Art der Schleife. Lassen Sie uns die Verwendung von yield besprechen, um eine Funktion in einen Generator umzuwandeln.

Die Funktion yield wurde bei der Entwicklung von PHP5 auf die Tagesordnung gesetzt und die Version PHP5.5 wurde offiziell hinzugefügt.

Was die Verwendung von yield betrifft, habe ich gesehen, dass die meisten Artikel bei der Verwendung von yield zum Einfügen von Daten in foreach hängen bleiben. Heute möchte ich Ihnen die gesamte Syntax von erklären Generator.

Verwandte Lernempfehlungen: PHP-Programmierung vom Einstieg bis zur Beherrschung

Offizielle Website-Erklärung

Generator Ermöglicht Ihnen, Code innerhalb eines foreach-Codeblocks zu schreiben, um einen Datensatz zu durchlaufen, ohne ein Array im Speicher zu erstellen, was Ihre Speichergrenze erreichen oder erhebliche Verarbeitungszeit in Anspruch nehmen würde. Stattdessen können Sie eine Generatorfunktion schreiben, genau wie eine normale benutzerdefinierte Funktion, und statt einer normalen Funktion, die nur einmal zurückgibt, kann der Generator yield so oft wie nötig verwendet werden, um die benötigten Werte zu generieren wiederholt werden.

Ich habe mir die offizielle Website angesehen und ihm erklärt: Die Syntax des php.net-Generators. Ich kannte jedes Wort, schien aber dennoch die Bedeutung zu verstehen. Auf der offiziellen Website betrachten wir hauptsächlich zwei Teile: die Syntax von

  1. yield.

  2. Codebeispiel.

Lassen Sie uns zunächst über die Syntax sprechen. Die linke Seite von yield ist eine Zuweisungsanweisung und die rechte Seite kann ein Wert (oder Ausdruck) sein. Yield führt zunächst den Ausdruck rechts aus und sendet den Wert $value an die Außenseite des Generators. Wenn der Generator den Wert empfängt, führt er die Anweisung links von yield aus und weist den Wert $data zu.

<?phpfunction func(){
    $data = (yield [$express]);}
Nach dem Login kopieren

Die Syntax ist so, ich denke, jeder ist immer noch etwas verwirrt, also nimm a Schauen Sie sich das Codebeispiel unten auf der offiziellen Website an. Die Beispiele sind gemischt.

Achten Sie auf die Klammern um yield. Wenn es sich um php5.5 handelt, ist die Priorität von $express auf der rechten Seite die Beurteilung und kann niedriger sein als die Zuweisungsanweisung von $data auf der links. Verwenden Sie also yield in php5. Die rechte Seite von yield ist ein ausführbarer Ausdruck, und die linke Seite muss Rückgaben akzeptieren und Werte zuweisen, daher ist diese Klammer erforderlich. Dieses Problem wird in PHP7 nicht auftreten.

Lernen Sie es anhand von Beispielen

Ob das Erlernen der menschlichen Sprache oder der Computersprache, alles beginnt mit der Nachahmung

Für eine Beschreibung in menschlicher Sprache ist es nicht so klar, deshalb möchte ich Ihnen anhand von Beispielen erklären, was es kann und was nicht.

Ich habe den entsprechenden Code auf Gitee abgelegt. Ich hoffe, Sie können ihn in Ihre lokale Umgebung kopieren und selbst ausführen, um ihn zu erleben, was Ihnen hilft, den folgenden Inhalt zu verstehen.

git clone gitee.com/xupaul/PHP-generator-yie...

So generieren Sie einen Generator

Definieren Sie zunächst eine Funktion, schreiben Sie das Schlüsselwort yield in die Funktion und weisen Sie diesen Funktionsaufruf einer Variablen zu. Ein Generator wird erzeugt.

Der Code /php-yield-test/yieldFunctions.php ist ein Generator, der mehrere Generatoren entsprechend unterschiedlicher Syntaxkombinationen definiert.

Testcode /php-yield-test/whatIsGenerator.php, mit dem überprüft wird, welche Funktionen einen Generator bilden können und welche nicht. Die laufenden Ergebnisse lauten wie folgt:

test result

  1. Die Funktion muss das Schlüsselwort yield enthalten. Die Funktion kann eine vollständige Wiedergabefunktion oder eine Klassenmethode sein.
  2. Auch wenn yield definitiv nicht ausgeführt wird, wird ein Generator generiert. Siehe: yield_func4
  3. Das bloße Schlüsselwort yield reicht aus (kein Senden, keine Verarbeitung externer Eingaben). Siehe: Yield_func2
  4. Die Verwendung eines Generators innerhalb einer Funktion macht sich selbst nicht zu einem Generator, siehe: yield_func5
  5. Beim Ausführen yield direkt in der Auswertungsfunktion wird ein Fehler gemeldet, siehe: yield_func11

Ja, es spielt keine Rolle, ob es foreach-, while- und for-Anweisungen in der Funktion gibt. Der Schlüssel ist yield. Die Typbeurteilung des Generators erfolgt mit $gen instanceof Generator

Generatorfunktionen

Generatorobjekte werden von Generatoren zurückgegeben.

Generatorobjekte können nicht durch neu instanziiert werden.

  • Generator::current — 返回当前产生的值
  • Generator::key — 返回当前产生的键
  • Generator::next — 生成器继续执行
  • Generator::rewind — 重置迭代器
  • Generator::send — 向生成器中传入一个值
  • Generator::throw — 向生成器中抛入一个异常
  • Generator::valid — 检查迭代器是否被关闭
  • Generator::__wakeup — 序列化回调
  • Gengerator::getReturn - Get the return value of a generator

摘自 php.net generator

看着以上方法,是不想起了Iterator, 他们的确很像。同时注意,官网zh语言版本的文档没有索引方法getReturn,访问也是404。文档以en版为准,ch做参考。

以上就是生成器所有的方法,我们一个个来看。

测试方法代码 /php-yield-test/generatorMothod.php, 这里面对每个方法都有使用举例,运行结果如下。

run result 2

run result 3

好接下来对举例做个一一讲解。

Generator::current

  • 返回当前产生的值
<?phpfunction yield_func(){
    yield 12;
    return &#39;a&#39;;}$gen = yield_func();$re = $gen->current();echo &#39;current return : &#39; . $re;
Nach dem Login kopieren

输出:

current return : 12
Nach dem Login kopieren

看到 php-yield-test/generatorMothod.php 代码。

通过第一个代码事例,可得,对一个generator调用current方法,才算真正开始执行。执行到yield为止。如果不能命中yield,则执行到函数结束。

非generoator会立马执行并得到结果,而非一个生成器对象。

通过例子2,调用current一次,两次呢,第一次可以看到代码执行日志,第二次,只是把上一次的结果返回给我们而已,并不是让该生成器重新执行。

通过例子1,调用该函数还会获取到返回值,返回的内容就是 yield 表达式左边的内容。如果表达式无内容,则是NULL.

Generator::send

  • 向生成器yield点中传入一个值,并返回下一次current值。
<?phpfunction yield_func(){
    $data = yield 12;
    echo &#39;get yield data: &#39; . $data;
    return &#39;a&#39;;}$gen = yield_func();$re = $gen->current();$gen->send(32);
Nach dem Login kopieren

输出:

get yield data: 32
Nach dem Login kopieren

例子3,是一个current,send的常规调用。调用current代码运行yield等到用户send输入参数。接收到输入后,继续运行。current能够接收到yield弹出的值,send返回值为空。

例子4,直接调用send,相当于调用current,send。不过current的返回值,并不会通过send传给用户。

例子21中,可以看到直接调用send(1),会运行生成器,并向第一个yield处输入1,继续运行至下一个yield的返回值value。所以,$gen->send(2),和 $gen->current() 结果都是同一个值。

也就是说:跳过current,直接调用send,会丢失第一次yield的弹出值。

Generator::next

  • 跳过中断,并让生成器继续执行
<?phpfunction yield_func(){
    echo &#39;run to code line: &#39; . __LINE__ . PHP_EOL;
    yield;
    echo &#39;run to code line: &#39; . __LINE__ . PHP_EOL;
    return $result;}$gen = yield_func();$gen->current();echo &#39;current called&#39; . PHP_EOL;$gen->next();
Nach dem Login kopieren

输出:

run to code line: 4current called
run to code line: 6
Nach dem Login kopieren

例子5,这是一个较为常规的调用,调用current代码运行yield等到用户输入,这是调用next跳过,让代码继续运行。

例子6,直接调用next,相当于调用currentnext。而且通过最后打印$result, 我们发现怎么有点像在调用 $gen->send(NULL);

Generator::rewind

  • 重置迭代器
<?phpfunction yield_func(){
    echo &#39;run to code line: &#39; . __LINE__ . PHP_EOL;
    $result = yield 12;
    echo &#39;run to code line: &#39; . __LINE__ . PHP_EOL;}$gen = yield_func();echo &#39;call yield_func rewind &#39; . PHP_EOL;$gen->rewind();
Nach dem Login kopieren

输出:

call yield_func rewind 
run to code line: 4
Nach dem Login kopieren

例子7,8 中,发现调用该方法,会导致隐式调用current

例子9 中,发现在执行过一个yield代码段后,再次调用该方法,会导致报错(哪怕该 生成器已结束)。

Generator::throw

  • 向生成器中抛入一个异常
<?phpfunction yield_func(){
    try {
        $re = yield &#39;exception&#39;;
    } catch (Exception $e) {
        echo &#39;catched exception msg: &#39; .$e->getMessage();
    }}$gen = yield_func();$gen->throw(new \Exception(&#39;new yield  exception&#39;));
Nach dem Login kopieren

输出:

catched exception msg: new yield  exception
Nach dem Login kopieren

通过以上简单的例子可得,throw 就是让yield这行代码产生异常,让外面的try catch 捕获我们生成的那个异常。

例子11中,构造生成器,并调用current方法,运行到yield处,再调用throw,就能捕获到异常。

例子12中,当调用send方法,跳过函数内yield代码时,再调用throw传入异常,就没法捕获了。

Generator::valid

  • 检查迭代器是否被关闭
<?phpfunction yield_func(){
    yield 12;
    return &#39;a&#39;;}$gen = yield_func();$gen->send(1);$check = $gen->valid();echo &#39;the generator valid ? &#39; . intval($check);
Nach dem Login kopieren

输出:

the generator valid ? 0
Nach dem Login kopieren

例子12中,发现current被隐式调用。

例子13中,可得,当生成器运行到yield代码段时,用valid函数检查,都会返回true

所以,别问我是否已运行,问就是运行。该方法用来获取是否关闭状态,不是 是否运行状态!运行到底,运行到return就是 关闭状态。

Generator::key

  • 返回当前产生的键
<?phpfunction yield_func(){
    yield 1 => &#39;abc&#39;;}$gen = yield_func();echo &#39;value is :&#39; . $gen->current() . PHP_EOL;echo &#39;key is: &#39; . $gen->key() . PHP_EOL;
Nach dem Login kopieren

输出:

value is :abc
key is: 1
Nach dem Login kopieren

从以上例子中,可得yield可显示设置返回的key.

例子15 中,发现key的分发规律和PHP数组键值发放策略是差不多的,默认从0开始,未指定则是以上一个数字key+1作为当前的key.

例子16 中,我们又发现current被隐式调用。

Generator::__wakeup

  • Generator::__wakeup — 序列化回调
<?phpfunction yield_func(){
    yield 1 => &#39;abc&#39;;}$gen = yield_func();try {$ser = serialize($gen);} catch (\Exception $e) {
    print_r($e->getMessage());}
Nach dem Login kopieren

输出:

Serialization of &#39;Generator&#39; is not allowed
Nach dem Login kopieren

这是一个魔术方法,见 PHP 魔术方法,也就是说 生成器 不能被序列化成一个字符串。

例子17就不用说了,看下例子18,看样子序列化成功了。也就是说一个生成器做为一个方法可以被序列化,当函数变成生成器时,就不能被序列化了。

Generator::getReturn

<?phpfunction yield_func(){
    yield 1 => &#39;abc&#39;;
    return 32;}$gen = yield_func();$gen->send(0);echo &#39;call yield_func return, and get: &#39; . $gen->getReturn();
Nach dem Login kopieren

输出:

call yield_func return, and get: 32
Nach dem Login kopieren

该函数就是获取生成器最后的返回值。如果没有return语句,或者没有执行到return语句,调用该函数得到的就是NULL。

例子19 可得,getReturn 能够获取到生成器最后的返回值。

例子19、20 可得,当生成器没有执行到return语句,或者没有执行到最后时,调用getReturn是会导致报错。

综上所述

到这里,我们就发现rewind,next__wakeup 这两个函数感觉没啥叼用呢,为啥还存在呢,因为Generator继承Iterator,自然就有了rewind, next方法,PHP 虽然支持方法覆盖,但子类的访问修饰符 不能缩紧,所以Generator只能重写这两个方法。 __wakeup 继承自 stdClass

状态转换

看图:

PHP yield 生命周期图

画了两个状态转换图,上面的要细致,繁复一点。下面的精简版,便于快速理解。

总结

以上就是关于 PHP 生成器的基础内容,希望你看了后对它有更进一步认识。下一讲,我们手把手一起来做一个任务调度器,实战一下。

有问题欢迎提问,谢谢大家!

Verstehen der Verwendung des PHP-Yield-Coroutine-Generators

Das obige ist der detaillierte Inhalt vonVerstehen der Verwendung des PHP-Yield-Coroutine-Generators. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:learnku.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