Итератор в Python относится к объекту, по которому мы можем выполнять итерацию. iterator состоит из счетных значений, и эти значения можно просматривать одно за другим.
Итератор просто реализует протокол iterator в Python. Протокол итератора – это класс, который имеет два специальных метода, а именно __iter __() и __next __(). С помощью этих двух методов итератор может вычислить следующее значение в итерации.
С итераторами легко работать с последовательностями элементов в Python. Нам не нужно выделять вычислительные ресурсы всем элементам в последовательности, мы выполняем итерацию по одному элементу за раз, что помогает нам сэкономить место в памяти.
В этой статье мы изучим, как работать с итераторами в Python.
Итерируемые объекты
Итерируемый объект – это объект, способный возвращать итератор. Итерируемый объект может представлять, как конечные, так и бесконечные источники данных. Итерация прямо или косвенно реализует два метода: __iter __() и __next __(). Метод __iter __() возвращает объект-итератор, а метод __next __() помогает нам перемещаться по элементам в итеративном объекте.
Примеры итерируемых объектов в Python включают списки, словари, кортежи и наборы.
Создание итератора
В Python мы создаем итератор, реализуя для объекта методы __iter __() и __next __(). Рассмотрим следующий пример:
class IterationExample:
def __iter__(self):
self.x = 0
return self
def __next__(self):
y = self.x
self.x += 1
return y
classinstance = IterationExample()
element = iter(classinstance)
Мы создали итератор с именем element, который печатает числа от 0 до N. Сначала мы создали экземпляр класса и дали ему имя classinstance. Затем мы вызвали встроенный метод iter() и передали имя экземпляра класса в качестве параметра. Это создает объект-итератор.
Давайте теперь обсудим, как использовать итератор для фактического перебора элементов.
Метод next()
Метод next() помогает нам перебирать элементы итератора. Продемонстрируем это на примере, приведенном выше:
class IterationExample:
def __iter__(self):
self.x = 0
return self
def __next__(self):
y = self.x
self.x += 1
return y
classinstance = IterationExample()
element = iter(classinstance)
print(next(element))
print(next(element))
print(next(element))
print(next(element))
print(next(element))
print(next(element))
print(next(element))
print(next(element))
print(next(element))
print(next(element))
Вывод:
0 1 2 3 4 5 6 7 8 9
В приведенном выше скрипте мы вызвали метод next() и передали ему имя элемента итератора в качестве параметра. Каждый раз, когда мы это делаем, итератор переходит к следующему элементу в последовательности. Вот еще один пример:
# create a list list1 = [0, 5, 10, 15] # create an iterator element = iter(list1) ## use next() to traverse/iterate through the list elements # prints first element, 0 print(next(element)) # prints second element, 5 print(next(element)) ## next(element) is similar to element.__next__() # prints third element, 10 print(element.__next__()) # prints fourth element, 15 print(element.__next__())
Вывод:
0 5 10 15
В приведенном выше скрипте мы создали список с именем list1, который содержит 4 целых числа. Создан итератор с именем element. Метод next() помог нам перебрать элементы списка.
Итерация с помощью цикла for
Цикл for помогает нам перебирать любой объект, способный возвращать итератор. Например:
# create a list
list1 = [0, 5, 10, 15]
# create an iterator
element = iter(list1)
# iterate with a for loop
for x in element:
print(x)
Вывод:
0 5 10 15
В приведенном выше коде мы создали переменную с именем x, которая используется для перебора элемента итератора через цикл for.
Бесконечные итераторы
Бесконечный итератор – это итератор с бесконечным числом итераций. Мы должны быть особенно осторожны при работе с бесконечными итераторами. Рассмотрим следующий пример:
class IterationExample:
def __iter__(self):
self.x = 0
return self
def __next__(self):
y = self.x
self.x += 1
return y
classinstance = IterationExample()
element = iter(classinstance)
for x in element:
print(x)
Приведенный выше код будет работать вечно. Чтобы остановить это, вам придется вмешаться вручную. Вот еще один пример, демонстрирующий, как создать бесконечный итератор в Python:
class Infinite:
# Print all even numbers
def __iter__(self):
self.x = 0
return self
def __next__(self):
x = self.x
self.x += 2
return x
Код должен возвращать все четные числа, начиная с 0. Мы можем запустить код, как показано ниже:
>>> y = iter(Infinite()) >>> next(y) 0 >>> next(y) 2 >>> next(y) 4 >>> next(y) 6 >>> next(y) 8 >>> next(y) 10 >>>
И эта цепочка может продолжаться вечно. Это показывает, что с бесконечным итератором мы можем иметь бесконечное количество элементов без необходимости хранить их все в памяти.
В следующем разделе мы увидим, как мы можем реализовать механизм выхода из таких бесконечных итераторов.
Остановка итерации
В предыдущем разделе мы увидели, как создать бесконечный итератор в Python. Однако итераторы обычно не предназначены для бесконечных итераций в Python. Всегда удобно реализовать условие завершения.
Мы можем остановить выполнение итератора навсегда с помощью оператора StopIteration. Нам нужно только добавить условие завершения в метод __next __(), которое вызовет ошибку, как только будет достигнуто указанное количество итераций. Вот пример:
class StoppingIteration:
def __iter__(self):
self.x = 1
return self
def __next__(self):
if self.x <= 5:
y = self.x
self.x += 1
return y
else:
raise StopIteration
classinstance = StoppingIteration()
element = iter(classinstance)
for a in element:
print(a)
Вывод:
1 2 3 4 5
Выполнение останавливается после 5 итераций. Это из-за условия self.x <= 5:, добавленного в метод __next __(). Если итератор вызывается после достижения 5, он вызовет событие StopIteration. Рассмотрим пример, приведенный ниже:
class StoppingIteration:
def __init__(self, max = 0):
self.max = max
def __iter__(self):
self.x = 1
return self
def __next__(self):
if self.x <= self.max:
val = 3 ** self.x
self.x += 1
return val
else:
raise StopIteration
Давайте создадим итератор, а затем переберем его:
>>> y = StoppingIteration(3)
>>> z = iter(y)
>>> next(z)
3
>>> next(z)
9
>>> next(z)
27
>>> next(z)
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
next(z)
File "C:\Users\admin\iteration.py", line 17, in __next__
raise StopIteration
StopIteration
>>>
Условие завершения было реализовано в следующем разделе нашего кода:
if self.x <= self.max:
val = 3 ** self.x
Мы передали итератору значение 3, что означает, что итератор не должен выполнять итерацию более 27, то есть 3 ^ 3.
Заключение
Итераторы чрезвычайно полезны, особенно если вам нужно перебрать большую последовательность элементов. Итераторы позволяют выполнять итерацию по последовательности элементов по одному без необходимости загружать все элементы в память сразу.
В этой статье мы увидели, как создавать итераторы в Python и как перебирать элементы в итераторе. Мы также увидели, как создать бесконечный итератор и как добавить условие завершения к бесконечному итератору.