(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, станет однонаправленным объектом итератора и предоставит методы, с помощью которых можно управлять его состоянием, включая передачу в него и возвращения из него значений.