Книга: PyNEng
Назад: Итерируемый объект
Дальше: Generator

Итератор

Итераторы

Итератор (iterator) - это объект, который возвращает свои элементы по одному за раз.

С точки зрения Python - это любой объект, у которого есть метод __next__. Этот метод возвращает следующий элемент, если он есть, или возвращает исключение StopIteration, когда элементы закончились.

Кроме того, итератор запоминает, на каком объекте он остановился в последнюю итерацию.

В Python у каждого итератора присутствует метод __iter__ - то есть, любой итератор является итерируемым объектом. Этот метод просто возвращает сам итератор.

Пример создания итератора из списка:

In [3]: lista = [1, 2, 3]  In [4]: i = iter(lista) 

Теперь можно использовать функцию next(), которая вызывает метод __next__, чтобы взять следующий элемент:

In [5]: next(i) Out[5]: 1  In [6]: next(i) Out[6]: 2  In [7]: next(i) Out[7]: 3  In [8]: next(i) ------------------------------------------------------------ StopIteration              Traceback (most recent call last) <ipython-input-8-bed2471d02c1> in <module>() ----> 1 next(i)  StopIteration: 

После того, как элементы закончились, возвращается исключение StopIteration.

Для того, чтобы итератор снова начал возвращать элементы, его надо заново создать.

Аналогичные действия выполяются, когда цикл for проходится по списку:

In [9]: for item in lista:    ...:     print(item)    ...: 1 2 3 

Когда мы перебираем элементы списка, к списку сначала применяется функция iter(), чтобы создать итератор, а затем вызывается его метод __next__ до тех пор, пока не возникнет исключение StopIteration.

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

Файл как итератор

Один из самых распространенных примеров итератора - файл.

Файл r1.txt:

! service timestamps debug datetime msec localtime show-timezone year service timestamps log datetime msec localtime show-timezone year service password-encryption service sequence-numbers ! no ip domain lookup ! ip ssh version 2 ! 

Если открыть файл обычной функцией open, мы получим объект, который представляет файл:

In [10]: f = open('r1.txt') 

Этот объект является итератором, что можно проверить, вызвав метод __next__:

In [11]: f.__next__() Out[11]: '!\n'  In [12]: f.__next__() Out[12]: 'service timestamps debug datetime msec localtime show-timezone year\n' 

Аналогичным образом можно перебирать строки в цикле for:

In [13]: for line in f:     ...:     print(line.rstrip())     ...: service timestamps log datetime msec localtime show-timezone year service password-encryption service sequence-numbers ! no ip domain lookup ! ip ssh version 2 ! 

При работе с файлами, использование файла как итератора не просто позволяет перебирать файл построчно - в каждую итерацию загружена только одна строка. Это очень важно при работе с большими файлами на тысячи и сотни тысяч строк, например, с лог-файлами.

Поэтому при работе с файлами в Python чаще всего используется конструкция вида:

In [14]: with open('r1.txt') as f:     ...:     for line in f:     ...:         print(line.rstrip())     ...: ! service timestamps debug datetime msec localtime show-timezone year service timestamps log datetime msec localtime show-timezone year service password-encryption service sequence-numbers ! no ip domain lookup ! ip ssh version 2 ! 
Назад: Итерируемый объект
Дальше: Generator