Résumé sur les générateurs
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Les générateurs fournissent une façon simple de mettre en place des
itérateurs
sans le coût ni la complexité du développement d'une classe qui implémente
l'interface Iterator.
Un générateur offre un moyen pratique de fournir des données aux boucles foreach
sans
avoir à construire un tableau en mémoire à l'avance, ce qui pourrait amener le programme
à dépasser une limite de mémoire ou nécessiter un temps de traitement considérable pour les générer.
À la place, une fonction générateur peut être utilisée,
qui est identique à une
fonction normale,
mis à part le fait qu'au lieu de retourner
une seule fois, un générateur peut utiliser yield
autant de fois que nécessaire, afin de
fournir les valeurs à parcourir.
Comme avec les itérateurs, l'accès aléatoire aux données n'est pas possible.
Un exemple simple de ce mécanisme est la ré-implémentation
de la fonction range() sous la forme d'un générateur.
La fonction standard range() doit générer un tableau
contenant chaque valeur, et le retourner, ce qui peut conduire
à des tableaux de taille importante : par exemple, l'appel du code
range(0, 1000000) peut consommer nettement plus de
100 Mo de mémoire.
Comme alternative, nous pouvons implémenter un générateur
xrange()
, qui n'aura en besoin mémoire que la seule
création d'un objet Iterator, et devra garder trace
en interne du statut courant du générateur, ce qui revient à une
consommation mémoire inférieure à 1 Ko.
Exemple #1 Implémentation de la fonction range() sous la forme d'un générateur
<?php
function xrange($start, $limit, $step = 1) {
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Step must be positive');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be negative');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
/*
* Il est à noter que les fonctions range() et xrange() produisent le
* même affichage, ci-dessous.
*/
echo 'Nombres impairs à un seul chiffre depuis range() : ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Nombres impairs à un seul chiffre depuis xrange() : ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
?>
L'exemple ci-dessus va afficher :
Nombres impairs à un seul chiffre depuis range() : 1 3 5 7 9
Nombres impairs à un seul chiffre depuis xrange() : 1 3 5 7 9
Lorsqu'une fonction générateur est appelée,
un objet de la classe interne Generator est
retournée. Cet objet implémente l'interface Iterator
de la même façon qu'un objet itérateur, qui avance uniquement, le ferait,
et fournit les méthodes qui peuvent être appelées pour manipuler le statut
du générateur, y compris l'envoi des valeurs et leurs retours.