Итератор (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 !