Итератор и итерируемые объекты. Функции iter() и next()

Курс по Python: https://stepik.org/course/100707

На этом занятии мы узнаем, что такое итерируемые объекты и познакомимся со способами их перебора. Мы уже знаем, что в Python существуют объекты, содержащие последовательность некоторых элементов. Например, строки и списки. Так вот, существует универсальный механизм для перебора элементов этих и других подобных им объектов. Реализуется он через специальную конструкцию под названием итератор. То есть, каждый итерируемый объект предоставляет доступ к своим элементам через итератор. С помощью этого итератора можно один раз пройтись по всем элементам коллекции от начала до конца.

Чтобы получить доступ к итератору объекта, например, списка, нужно вызвать специальную функцию iter() и первым аргументом указать итерируемый объект. Например, возьмем список:

d = [5, 3, 7, 10, 32]

и для него вызовем функцию iter():

iter(d)

Смотрите, нам был возвращен объект-итератор для списка. Сохраним его через переменную it:

it = iter(d)

Все, теперь у нас есть итератор для однократного перебора элементов списка d. Далее, чтобы перебрать значения итерируемого объекта, используется функция next(), которой следует передать объект-итератор:

next(it)

Она осуществляет переход к следующему элементу (при первом вызове переходим к первому элементу) и возвращает значение этого элемента. Видим значение 5. Вызовем эту функцию еще раз:

next(it)

Итератор был перемещен на следующий элемент и возвратилось значение 3. И так можно пройтись до конца нашего списка:

next(it)
next(it)
next(it)

Если для последнего элемента вызвать функцию еще раз:

next(it)

то получим ошибку StopIteration.

Когда итератор дошел до конца коллекции, его уже нельзя вернуть назад и пройти все элементы заново. Для этого придется создавать новый итератор с помощью функции iter():

it = iter(d)

и заново перебирать все элементы:

next(it)

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

s = "python"

Также создаем итератор:

it_s = iter(s)

и перебираем символы функцией next():

next(it_s)
next(it_s)

Как видите, итератору все равно что перебирать, главное, чтобы сам объект поддерживал этот механизм, то есть, был итерируемым. Также следует иметь в виду, что доступ к элементам через итератор и по индексу:

s[2]

это совершенно разные способы обращения к элементам. К тому же не у всех итерируемых объектов есть возможность указания индексов.

Помимо строк и списков к итерируемым объектам также относится ранее рассмотренная функция:

r = range(5)

Для нее мы можем получить итератор:

it = iter(r)

и перебирать значения функцией next():

next(it)
next(it)

Когда я вам все это рассказываю, у вас, наверное, постоянно крутится вопрос: а зачем это надо? Мы и без всяких итераторов можем обращаться к элементам строк, списков и даже объекта range()? Да, все верно, если нам нужно извлечь какое-либо значение, скажем, из списка, то следует использовать индексы или срезы. То же самое и со строками. Но если нам в программе нужно перебирать итерируемые объекты самых разных типов, то единственный универсальный и безопасный способ это сделать – использовать итераторы. Например, так происходит в операторе цикла for. Мы можем ему указать перебрать любой итерируемый объект и он должен «уметь» это делать вне зависимости от типа этого объекта. Поэтому он обращается к итератору и перебирает элементы через этот универсальный механизм, пока не возникнет исключение StopIteration. Именно поэтому мы в цикле можем с легкостью перебирать и списки:

for x in [5, 3, 7, 10, 32]:
    print(x)

И строки:

for x in "python":
    print(x)

И объект range():

for x in range(1, 6):
    print(x)

И вообще любой другой тип объектов, которые поддерживают итератор, то есть, являются итерируемыми.

А что будет, если мы попробуем получить итератор для не итерированного объекта, например, числа:

iter(5)

В этом случае получим ошибку, что объект типа int не является итерируемым, то есть, не поддерживает итератор и перебор элементов. Действительно, число – это одно значение и перебирать тут нечего, поэтому оно относится к неитерируемым объектам. Соответственно, и в цикле for мы не можем указывать такие элементы:

for x in 5:
    print(x)

Перебрать одно число не получится. Здесь можно указывать только итерируемые объекты.

Надеюсь, из этого занятия вам стало понятно, что такое итератор и итерируемые объекты, как получать итератор с помощью функции iter() и как перебирать элементы функцией next(). Закрепите этот материал практическими заданиями, после чего жду всех вас на следующем уроке.

Курс по Python: https://stepik.org/course/100707

Видео по теме