(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Генераторы — легкий способ реализации простых итераторов без дополнительных ресурсов или сложностей, которые связаны с написанием класса, который реализует интерфейс Iterator.
Генератор помогает писать код, который использует foreach для перебора набора данных без необходимости создания массива в памяти, что может привести к превышению лимита памяти или значительного времени, чтобы его создать. Вместо этого можно написать функцию-генератор, которая аналогична обычной функции, за исключением того, что вместо возврата единственного значения генератор умеет возвращать (yield) результат столько раз, сколько необходимо для генерации значений, которые позволяют перебрать исходный набор данных.
Простой пример этого — переопределение функции range() как генератора. Стандартная функция range() генерирует массив, который состоит из значений, и возвращает его, что приводит к генерации больших массивов: например, вызов range(0, 1000000) займёт более 100 МБ оперативной памяти.
В качестве альтернативы можно создать генератор xrange()
,
который использует память только чтобы создать объект
Iterator и сохранить текущее состояние, что потребует
не больше 1 килобайта памяти.
Пример #1 Реализация функции range() как генератора
<?php
function xrange($start, $limit, $step = 1)
{
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Шаг должен быть положительным');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Шаг должен быть отрицательным');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
/* Обратите внимание, что и range() и xrange() дадут один и тот же вывод */
echo 'Нечётные однозначные числа с помощью range(): ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Нечётные однозначные числа через функцию xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
?>
Результат выполнения приведённого примера:
Нечётные однозначные числа через функцию range(): 1 3 5 7 9 Нечётные однозначные числа через функцию xrange(): 1 3 5 7 9
Когда функция-генератор вызывается, она возвращает объект встроенного класса Generator. Этот объект реализует интерфейс Iterator, станет однонаправленным объектом итератора и предоставит методы, с помощью которых можно управлять его состоянием, включая передачу в него и возвращения из него значений.