Рубрики
Без рубрики

Введение в итераторы Python

Автор оригинала: Nicholas Samuel.

Введение в итераторы Python

Что такое итераторы?

Итератор в Python относится к объекту, который мы можем итерировать. Итератор состоит из счетных значений, и можно пройти через эти значения одно за другим.

Итератор просто реализует протокол итератора Python. Протокол итератора-это класс Python, который поставляется с двумя специальными методами, а именно __iter__() и _ _ next__() . С помощью этих двух методов итератор может вычислить следующее значение в итерации.

С помощью итераторов нам легко работать с последовательностями элементов в Python. Нам не нужно распределять вычислительные ресурсы по всем элементам последовательности, скорее мы выполняем итерацию по одному элементу за раз, что помогает нам экономить пространство памяти.

В этой статье мы рассмотрим, как работать с итераторами в Python.

Итеративные объекты в Python

Iterable-это объект, способный возвращать итератор. Итерируемый может представлять как конечные, так и бесконечные источники данных. Итерируемый прямо или косвенно реализует два метода: __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() помогает нам перебирать элементы итератора. Продемонстрируем это на приведенном выше примере:

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: , добавленного в метод __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 "", line 1, in 
    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 и как перебирать элементы в итераторе. Мы также видели, как создать бесконечный итератор и как добавить конечное условие к бесконечному итератору.