Итераторы в Python с примерами

Итератор в 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 и как перебирать элементы в итераторе. Мы также увидели, как создать бесконечный итератор и как добавить условие завершения к бесконечному итератору.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *