Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про PHP: iterator, generator

Чем генераторы отличаются от обычных массивов и итераторов с точки зрения использования памяти и невозможности перемотки?

Вопрос проверяет, понимает ли кандидат, чем генераторы концептуально отличаются от массивов и классических итераторов, особенно в части потребления памяти и поведения при повторном обходе.

Короткий ответ

Генераторы создают значения "по требованию" и не хранят всю последовательность в памяти, тогда как массивы содержат все элементы сразу. Это делает генераторы гораздо более экономными по памяти при работе с большими данными. В отличие от многих массивоподобных структур, генератор обычно нельзя "перемотать" назад и пройти повторно — после завершения он исчерпывается. По сравнению с вручную реализованными итераторами, генераторы проще в коде, но дают меньше контроля над внутренним состоянием и перемоткой.

Длинный ответ

Отличия генераторов от массивов и обычных итераторов

Генераторы решают ту же задачу итерации по данным, но делают это другим способом, что влияет на память и поведение при обходе.

1. Генераторы vs массивы: модель памяти

Массивы и генераторы принципиально по-разному хранят данные.

Определение: Массив в PHP — это структура, которая хранит все элементы в памяти одновременно.
Определение: Генератор — это объект, который вычисляет и отдаёт элементы по мере запроса, а не хранит их все сразу.

Сравнение:

  1. Массивы

    • Все элементы уже есть в памяти.

    • Операции индексного доступа ($arr[1000]) быстрые, если элемент существует.

    • Если данных очень много, легко превысить лимит памяти.

  2. Генераторы

    • Значения создаются "на лету" при обходе.

    • В памяти одновременно находится только текущее значение (и небольшое состояние функции).

    • Можно работать с миллионными наборами данных или бесконечными последовательностями.

Пример отличия:

php

// А: массив — хранит все числа сразу
function buildArray(int $n): array
{
    $result = [];
    for ($i = 0; $i < $n; $i++) {
        $result[] = $i;
    }
    return $result; // большой массив в памяти
}

// Б: генератор — выдаёт числа по одному
function buildGenerator(int $n): Generator
{
    for ($i = 0; $i < $n; $i++) {
        yield $i; // значение по одному
    }
}

При n = 1_000_000 массив может занять сотни мегабайт памяти, а генератор — существенно меньше.

2. Генераторы vs обычные итераторы (классы Iterator)

До появления генераторов для сложной логики обхода приходилось писать собственные классы, реализующие Iterator или IteratorAggregate.

Определение: Итератор — объект, который предоставляет методы current, next, key, valid, rewind для пошагового обхода.

Что общего

И генераторы, и "ручные" итераторы:

  • позволяют использовать foreach

  • реализуют интерфейс Traversable

  • могут выдавать потенциально бесконечные/большие последовательности

Чем генераторы отличаются

  1. Простота реализации
    Генератор пишется в несколько строк с yield, а итератор — отдельным классом с несколькими методами.

  2. Явное управление перемоткой у итераторов
    В ручном итераторе вы сами пишете rewind(), и можете настроить, как именно он "перематывается":

    php

    class MyIterator implements Iterator {
        public function rewind() { /* курсор в начало */ }
        public function current() { /* текущее значение */ }
        public function key() { /* текущий ключ */ }
        public function next() { /* шаг вперёд */ }
        public function valid() { /* есть ли элемент */ }
    }
    

    У генератора rewind() вызывается автоматически и работает один раз при первом входе в генератор.

  3. Гибкость состояния
    В итераторе вы сами управляете внутренним состоянием (например, ресурсами соединений, чтением файла), а в генераторе это состояние обычно привязано к стеку вызовов функции. Для большинства задач этого достаточно, но очень кастомное поведение иногда проще реализовать итератором.

3. Невозможность "перемотки" генератора

Ключевое свойство генераторов — они, как правило, одноразовые:

  1. Вы создаёте генератор:
    php

    $gen = buildGenerator(3);
    
  2. Идёте по нему foreach — значения выдаются по очереди.

  3. После окончания генератор "исчерпан" — повторно пройти по нему нельзя (без создания нового генератора).

Пример:

php

$gen = buildGenerator(3);

foreach ($gen as $v) {
    echo $v; // 0 1 2
}

foreach ($gen as $v) {
    echo $v; // ничего, генератор уже завершён
}

Это поведение важно понимать: генератор — это не "коллекция", а поток данных.

Если вам нужна перемотка — создавайте новый генератор заново или используйте структуру данных, которая хранит элементы (массив, коллекция).

4. Типичные сценарии применения генераторов

Генераторы особенно полезны там, где:

  1. Обрабатываются большие объёмы данных

    • чтение больших файлов построчно

    • обработка больших выборок из БД

    • стриминг данных из API

  2. Последовательность логически бесконечна

    • генерация последовательностей чисел

    • потоки событий

  3. Нужно уменьшить задержку
    Можно выдавать первые элементы до того, как будут готовы все остальные (например, стриминг).

5. Вывод

Генераторы отличаются от массивов и обычных итераторов тем, что:

  • не хранят все данные в памяти сразу

  • часто являются одноразовыми и не поддерживают "перемотку" после завершения

  • проще в написании, чем классы-итераторы, но дают меньше ручного контроля

Использовать генераторы стоит тогда, когда для вас важнее экономия памяти и потоковая обработка данных, а не произвольный доступ и многократный повторный обход без пересоздания источника.

  • Аватар

    PHP Guru

    Mikhail Savin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    4

  • Сложность:

    7

Навыки

  • PHP

    PHP

Ключевые слова

#iterator

#generator

Подпишись на PHP Developer в телеграм

  • Аватар

    PHP Guru

    Mikhail Savin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.