Tout d'abord, jetons un coup d'œil à la manière dont cela est introduit dans la documentation officielle PHP : les générateurs offrent un moyen plus simple d'implémenter une itération d'objet simple. Par rapport à la manière de définir une classe pour implémenter l'interface Iterator, la surcharge de performances. et la complexité sont considérablement réduites.
Après avoir lu cette phrase, nous pouvons obtenir plusieurs mots-clés : itération d'objet, interface Iterator, surcharge de performances, relativement abstrait, parler est bon marché montrez-moi le code, commençons par l'exemple le plus classique de générateur Commençons .
La fonction range() en PHP créera un tableau contenant l'unité de plage spécifiée dans la mémoire et la renverra lorsqu'elle sera utilisée. De manière générale, il n'y a rien de mal à cela, mais lorsque le paramètre de limite transmis est saisi. c'est très grand, cela signifie que le tableau qui sera créé dans la mémoire sera également très grand. C'est trop effrayant. C'est le rythme de l'éclatement de la mémoire. À ce stade, nous pouvons utiliser le générateur pour implémenter une fonction range plus efficace (le code suivant est une version simplifiée de la documentation officielle PHP) :
function xrange($start, $limit, $step = 1) { //校验参数,此处省略 for ($i = $start; $i <= $limit; $i += $step) { //向外产出值 yield $i; } } //xrange此时返回的是一个生成器对象 $gen = xrange(1, 9); //对生成器进行迭代 foreach ($gen as $number) { echo "$number "; }
Les fonctions xrange et range ont ici le même effet. , les deux génèrent une variable itérable, mais la différence est que la fonction range est un peu comme ce qu'on appelle souvent "préchargement" dans ORM, tandis que xrange est un "chargement paresseux" et attend seulement que l'itération atteigne ce point pour générer la valeur correspondante. , donc xrange n'a pas besoin d'allouer de gros blocs de mémoire pour stocker les variables, ce qui économise considérablement la mémoire et améliore l'efficacité.
Résumons maintenant les similitudes et les différences entre les générateurs et les fonctions ordinaires :
Le générateur doit contenir le mot-clé rendement (utilisé pour générer des résultats), et peut être Apparaît plusieurs fois. Dans les fonctions ordinaires, return ne peut être utilisé que pour renvoyer des résultats vers l'extérieur, et la fonction a été exécutée
Un générateur ne peut pas renvoyer une valeur via return ; une erreur de compilation. Erreur fatale PHP : les générateurs ne peuvent pas renvoyer de valeurs en utilisant "return" (Remarque : cela ne se passera pas mal sous PHP7, mais cela mettra fin au générateur et continuera à s'exécuter. Autrement dit, l'appel de la méthode valid() le fera. return false. Cependant, en PHP5, return empty est une syntaxe valide et il terminera le générateur et poursuivra l'exécution)
L'objet Générateur est renvoyé par le générateur, $gen dans le code ci-dessus C'est juste un objet générateur. Notez que l'objet générateur est différent des objets des autres classes. Il ne peut pas être créé via le mot-clé new et ne peut être obtenu qu'à partir de la fonction générateur. Tout d'abord, jetons un coup d'œil au résumé de la classe Generator pour voir sa composition :
Generator implements Iterator { /** * 返回当前产生的值(yield后面表达式的值) */ public mixed current ( void ) /** * yield的键(yield 'key'=>'val';) */ public mixed key ( void ) /** * 从上一个yield之后继续执行,直到下一个yield */ public void next ( void ) /** * 重置迭代器(对于生成器并没什么卵用) */ public void rewind ( void ) /** * 向生成器中传入一个值,并从上一个yield之后继续执行 */ public mixed send ( mixed $value ) /** * 向生成器中抛出一个异常,并从上一个yield之后继续执行 */ public void throw ( Exception $exception ) /** * 检查迭代器是否被关闭(false表示已关闭) */ public bool valid ( void ) /** * 序列化回调,但是生成器不能被序列化,因此会抛出一个异常 */ public void __wakeup ( void ) }
À partir du résumé de la classe ci-dessus, nous pouvons voir que la classe Generator implémente l'interface Iterator, elle a donc les caractéristiques d'un itérateur. De plus, il ajoute les méthodes send(), throw() et __wekeup(). Les descriptions des méthodes pertinentes ont été commentées et ne seront pas répétées ici.
J'ai beaucoup écrit et j'ai trouvé que mon écriture n'était pas bonne, alors autant faire un dessin pour avoir une idée (les images ne sont pas belles non plus, alors fais avec, 2333) <br/>
Jetons ensuite un coup d'œil au mot clé rendement. Sa forme d'appel la plus simple ressemble au retour d'une fonction normale. La différence est qu'un retour normal renverra un. value et termine l'exécution de la fonction, tandis que rendement renvoie une valeur au code qui parcourt ce générateur et met simplement en pause l'exécution de la fonction du générateur.
Il s'agit d'une expression de rendement typique : $data = rendement $key => $value;. Cette expression comprend deux parties :
Remarque : PHP5 nécessite des parenthèses $data = (yiel. d $key => $value);, sinon une erreur de compilation se produira, PHP7 n'a pas besoin de s'en soucier<br/>Copier après la connexion
L'une est l'expression après l'expression de rendement, cela peut être un seul valeur ou une paire clé-valeur, correspondant à un élément du tableau. Cette partie de l'expression est renvoyée à l'appel de la couche supérieure, c'est-à-dire que la couche supérieure peut recevoir la valeur via la méthode actuelle ou exécuter le retour de l'envoi. method. Value;
L'autre élément est le mot-clé rendement lui-même. Personnellement, je le comprends comme un récepteur, qui recevra la valeur transmise par la méthode d'envoi. valeur de l'expression de rendement entière. La valeur peut être reçue par la variable de gauche.
Cela peut être un peu abstrait, mais regardons l'image ci-dessus : <br/>
PHP7 a ajout du mot-clé rendement From, cette syntaxe autorise les valeurs de rendement provenant d'autres générateurs, d'objets Traversable ou de tableaux via la fonction rendement de génération. Les différentes caractéristiques de rendement de sont les mêmes que celles de rendement, qui génère des données, mais les expressions qui suivent sont différentes. Regardons un exemple (tiré de la documentation officielle PHP) :
function count_to_ten() { yield 1; yield 2; yield from [3, 4]; //生成数组 yield from new ArrayIterator([5, 6]); //生成可遍历对象 yield from seven_eight(); //生成生成器对象 yield 9; yield 10; } function seven_eight() { yield 7; yield from eight(); } function eight() { yield 8; } foreach (count_to_ten() as $num) { echo "$num "; } //输出:1 2 3 4 5 6 7 8 9 10
yield from以方便我们编写比较清晰生成器嵌套,这点可以类比于函数中的嵌套调用,当函数A中调用另一个函数B,此时会等B执行完成并返回,方才继续执行。在没有yield from的时候,实现生成器嵌套需要自己实现栈并进行压栈和弹出操作以达到相同效果,那是多么痛苦的操作。
相关推荐:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!