Генераторы предоставляют простой способ реализации простых итераторов без накладных расходов или сложности реализации класса, реализующего интерфейс Iterator .
Генератор позволяет вам писать код, который использует foreach для перебора набора данных без необходимости построения массива в памяти, что может привести к превышению лимита памяти или потребовать значительного времени обработки для генерации. Вместо этого вы можете написать функцию генератора, которая аналогична обычной функции , за исключением того, что вместо однократного возврата генератор может возвращать столько раз, сколько необходимо, чтобы предоставить значения для итерации.
Простым примером этого является повторная реализация функции 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('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;
}
}
}
/*
* Note that both range() and xrange() result in the same
* output below.
*/
echo 'Single digit odd numbers from range(): ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Single digit odd numbers from xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
?>
Приведенный выше пример выведет:
Одноразрядные нечетные числа из диапазона(): 1 3 5 7 9
Одноразрядные нечетные числа из xrange(): 1 3 5 7 9
Объекты - генераторы
При вызове функции генератора возвращается новый объект внутреннего класса Generator . Этот объект реализует интерфейс Iterator почти так же, как и объект итератора, работающий только в прямом направлении, и предоставляет методы, которые можно вызывать для управления состоянием генератора, включая отправку значений в него и возврат значений из него.
0 комментариев