Классы-иттераторы
В Python 2.2 появился специальный интерфейс для итераторов, благодаря чему итераторы стало возможным описывать единообразно. Тот же пример с использованием стандартного интерфейса:
class Fibonacci:
"""Итератор последовательности Фибоначчи"""
def __init__(self, max):
self.n, self.a, self.b, self.max = 0, 0, 1, max
def __iter__(self):
return self
def next(self):
if self.n < self.max:
a, self.n, self.a, self.b = self.a, self.n+1, self.b, self.a+self.b
return a
else:
raise StopIteration
Заметьте, что по сравнению с предыдущим примером произошли три изменения. Во-первых, добавился метод __iter__(), который возвращает объект-итератор (в нашем примере -- сам объект). Во вторых, вместо метода __getitem__(), через который цикл for получал значения последовательности, применен метод next(), который является необходимым для объекта-итератора в Python. В-третьих, теперь в качестве сигнала завершения итераций используется исключение StopIteration.
В Python также появилась встроенная функция iter(), которая создает итератор для некоторой последовательности. Пример:
s = [1, 2, 3, 4, 5]
siter = iter(s)
for i in siter:
print i
Конечно, в данном случае итератор нужен не был, так как оператор for прекрасно работает с последовательностями.
Есть и другая форма функции iter(), которая в качестве первого аргумента принимает функцию без аргументов, а в качестве второго аргумента -- стоповое значение.
В следующем примере происходит ввод и суммирование чисел. Итерации останавливаются при вводе числа 0:
s = 0
for i in iter(input, 0):
s += i
print s
Кстати, построчное чтение из файла можно теперь записать так:
f = open("file.txt")
for l in iter(f.readline, ""):
print l # делаем что-то с очередной строкой файла
Итераторы применяются в нескольких стандартных модулях Python. Например, с помощью finditer() из модуля re легко получить в обычном цикле for все куски строки, соответствующие регулярному выражению:
for i in re.finditer("[0-9]+", "12 3 1 23 fff 1678"):
print int(i.group())