0Pricing
Python Academy · Урок

Протокол итератора

Разберитесь с __iter__ и __next__

«Протокол итератора» — бесплатный урок Python Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.

Что такое итерация

Когда Вы пишете цикл for по списку, строке или словарю, Python незаметно использует протокол итератора.

Объект, по которому можно выполнять цикл, называется итерируемым объектом. Объект, который фактически выдаёт значения по одному, называется итератором.

for ch in 'abc':
    print(ch)

Получение итератора и следующего значения

Итерацию обеспечивают две встроенные функции:

  • iter(obj) запрашивает у итерируемого объекта его итератор.
  • next(it) запрашивает у итератора следующее значение.

Когда значения заканчиваются, next() вызывает исключение StopIteration.

it = iter([10, 20, 30])
print(next(it))
print(next(it))
print(next(it))

StopIteration

Если вызвать next() на один раз больше необходимого, возникнет исключение StopIteration. Цикл for автоматически перехватывает его и корректно останавливается.

it = iter([1])
print(next(it))
try:
    next(it)
except StopIteration:
    print('No more items')

Два специальных метода

Чтобы создать собственный итератор, реализуйте два метода:

  • __iter__ возвращает сам объект-итератор.
  • __next__ возвращает следующее значение или вызывает исключение StopIteration.
class Count:
    def __init__(self, n):
        self.i = 0
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.i >= self.n:
            raise StopIteration
        self.i += 1
        return self.i

for x in Count(3):
    print(x)

Итерируемый объект и итератор

Итерируемому объекту достаточно иметь __iter__. Итератору нужны и __iter__, и __next__.

Списки являются итерируемыми объектами, но не итераторами: каждый вызов iter() возвращает новый итератор.

nums = [1, 2, 3]
print(iter(nums) is iter(nums))
it = iter(nums)
print(it is iter(it))

Итераторы исчерпываются один раз

Итератор можно использовать только один раз. После достижения конца он остаётся пустым. Чтобы повторить цикл, создайте новый итератор.

it = iter([1, 2])
print(list(it))
print(list(it))

Итератор, подобный диапазону

Создадим собственный итератор, который ведёт себя как простой счётчик. Обратите внимание: состояние хранится в экземпляре.

class EvenUpTo:
    def __init__(self, limit):
        self.cur = 0
        self.limit = limit
    def __iter__(self):
        return self
    def __next__(self):
        if self.cur > self.limit:
            raise StopIteration
        value = self.cur
        self.cur += 2
        return value

print(list(EvenUpTo(8)))

Разделение итерируемого объекта и итератора

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

class Bag:
    def __init__(self, items):
        self.items = items
    def __iter__(self):
        return BagIterator(self.items)

class BagIterator:
    def __init__(self, items):
        self.items = items
        self.i = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.i >= len(self.items):
            raise StopIteration
        v = self.items[self.i]
        self.i += 1
        return v

b = Bag(['x', 'y'])
print(list(b))
print(list(b))

Получение следующего значения по умолчанию

next(it, default) возвращает значение по умолчанию вместо вызова исключения StopIteration, если итератор пуст. Это удобно для безопасной проверки следующего значения.

it = iter([42])
print(next(it, 'done'))
print(next(it, 'done'))

Итераторы экономят память

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

class Naturals:
    def __init__(self):
        self.n = 0
    def __iter__(self):
        return self
    def __next__(self):
        self.n += 1
        return self.n

it = iter(Naturals())
print(next(it), next(it), next(it))

Встроенные функции, потребляющие итераторы

Многие встроенные функции принимают любой итератор: sum, max, min, sorted, list, tuple. Они извлекают значения, пока не возникнет StopIteration.

class Count:
    def __init__(self, n):
        self.i = 0
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.i >= self.n:
            raise StopIteration
        self.i += 1
        return self.i

print(sum(Count(5)))
print(max(Count(5)))

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете протокол итераторов.

Итоги

Вы изучили протокол итераторов:

  • iter() получает итератор, а next() извлекает значения.
  • StopIteration обозначает конец, а цикл for обрабатывает это исключение.
  • Пользовательские итераторы реализуют __iter__ и __next__.
  • Итераторы можно использовать только один раз, и они экономно расходуют память.

Далее Вы позволите Python создавать итераторы за Вас с помощью yield.

Часто задаваемые вопросы

Урок «Протокол итератора» бесплатный?

Да — полный текст урока «Протокол итератора» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.

Чему я научусь в уроке «Протокол итератора»?

Разберитесь с __iter__ и __next__ Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Python Academy?

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

Сколько времени занимает урок «Протокол итератора»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Python Academy?

Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Протокол итератора
  2. Функции-генераторы
  3. Выражения-генераторы
  4. yield from и делегирование
← Назад к Python Academy