Sobes.tech
Назад к вопросам
Junior — Middle
65

Как отличить итератор от объекта, поддерживающего протокол итерации?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Итератор — это объект, который хранит состояние обхода и умеет возвращать элементы по одному. Объект, поддерживающий протокол итерации, — это более широкий случай: он умеет создать итератор через __iter__(). На практике итератор всегда итерируемый, но не каждый итерируемый объект является итератором.

Определение:

В Python итерируемый объект — это объект, по которому можно пройти в цикле for. Для этого у него должен быть метод __iter__(), возвращающий итератор, либо старый вариант — __getitem__() с индексами от 0.

Итератор — это объект с двумя обязательными свойствами: он возвращает следующий элемент через __next__() и сам себя возвращает в __iter__(). Когда элементы заканчиваются, он возбуждает StopIteration.

Проще говоря: итерируемый объект можно “запустить” в обход, а итератор уже сам хранит текущее место обхода.

Пример использования:

# Итерируемый объект, но не итератор
lst = [1, 2, 3]

it = iter(lst)   # получаем итератор
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3

# Сам список можно итерировать заново:
print(list(lst))  # [1, 2, 3]

Пояснение кода:

  1. lst — это список, то есть итерируемый объект.
  2. Вызов iter(lst) создает из списка итератор.
  3. next(it) последовательно забирает элементы из итератора.
  4. Когда элементы заканчиваются, следующий next(it) вызовет StopIteration.
  5. Сам список не “расходуется” и может быть итерирован повторно, потому что он не хранит текущее состояние обхода как итератор.

Если нужен прямой пример разницы через встроенные проверки:

lst = [1, 2, 3]
it = iter(lst)

print(hasattr(lst, "__iter__"))   # True
print(hasattr(lst, "__next__"))   # False

print(hasattr(it, "__iter__"))    # True
print(hasattr(it, "__next__"))    # True

Ключевые моменты:

  • Итерируемый объект отвечает на вопрос: “можно ли по нему пройтись?”
  • Итератор отвечает на вопрос: “как получить следующий элемент прямо сейчас?”
  • for сначала вызывает iter(...), а затем многократно next(...).
  • Итератор — это одноразовое состояние обхода; после завершения его обычно нельзя “перемотать” без создания нового.
  • Все итераторы являются итерируемыми, но не все итерируемые объекты являются итераторами.
  • Типичный итерируемый объект: список, строка, dict; типичный итератор: результат iter(...), генератор.