Что из себя представляет итератор в Python. Создаем свой собственный итератор

1. Итератор языка Python

В этой статье, посвященной итераторам и их применению в языке Python, мы также рассмотрим создание своих собственных методов __iter__() и __next__(), соберем свой собственный итератор, рассмотрим всю пользу итераторов и закрепим наши знания на примерах.

Итак, начинаем наш туториал по итераторам в Python.

2. Кто такие эти ваши итераторы?

Итератор в языке программирования Python — это объект, который вы можете перебирать. То есть он возвращает по одному объекту за раз. Итератор Python, неявно реализован в таких конструкциях, как циклы for, comprehension’ах и генераторах Python. Функции iter() и next() как раз и образуют протокол итератора.

Если мы можем получить итератор от объекта в Python, значит он итерабельный. Например, списки Python, кортежи и строки.

3. А как создать итератор?

Чтобы собрать итератор python3, мы используем функции iter() и next(). Давайте начнем с iter(), чтобы создать итератор.

Сначала мы создаем список, который содержит все четные числа от 2 до 10.

evens=[2,4,6,8,10]

Затем мы применяем функцию iter() к этому списку Python, чтобы создать объект итератора. Мы храним его в переменной evenIterator.

evenIterator=iter(evens)
evenIterator
<list_iterator object at 0x05E35410>

Помните, итератор можно получить не только для списка, кортежи и даже множества отлично подойдут.

iter((1,3,2))
<tuple_iterator object at 0x05E35550>

Теперь, чтобы получить доступ к первому элементу, мы применяем функцию next() к объекту итератора Python.

next(evenIterator)
2
next(evenIterator)
4
next(evenIterator)
6
next(evenIterator)
8
next(evenIterator)
10

Мы достигли конца списка. Когда мы вызываем его еще раз, мы провоцируем ошибку StopIteration (исключение). Интерпретатор сразу же выбрасывает его.

next(evenIterator)
Traceback (most recent call last):
File “<pyshell#442>”, line 1, in <module>
next(evenIterator)
StopIteration

С методом iter() разобрались, посмотрим на __next__()

Итак, вы можете пройтись по итератору в Python, используя метод __next __() вместо next(). (Ну, мало ли…)

nums=[1,2,3]
numIter=iter(nums)
numIter.__next__()
1
>>> next(numIter)
2
>>> numIter.__next__()
3
>>> numIter.__next__()
Traceback (most recent call last):
File “<pyshell#448>”, line 1, in <module>
numIter.__next__()
StopIteration

Мы можем увидеть этот метод с помощью функции dir().

>>> dir(numIter)
[‘__class__’, ‘__delattr__’, ‘__dir__’, ‘__doc__’, ‘__eq__’, ‘__format__’, ‘__ge__’, ‘__getattribute__’, ‘__gt__’, ‘__hash__’, ‘__init__’, ‘__init_subclass__’, ‘__iter__’, ‘__le__’, ‘__length_hint__’, ‘__lt__’, ‘__ne__’, ‘__new__’, ‘__next__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__setstate__’, ‘__sizeof__’, ‘__str__’, ‘__subclasshook__’]

4. Цикл for для итераторов Python

Вы также можете использовать цикл for в Python для итерации по какому-нибудь итерируемому объекту, например, по списку Python или по кортежу.

for i in 'Python':
    print(i)
P
y
t
h
o
n

Но как это на самом деле реализовано? Давайте взглянем.

iter_obj=iter('Python')
while True:
    try:
        i=next(iter_obj)
        print(i)
    except StopIteration
         break
P
y
t
h
o
n

Это была простая версия. Вот как на самом деле реализован вышеприведенный цикл for.

5. Наконец создаем свой собственный итератор

Теперь вы знаете, как использовать итератор с функциями iter() и next(). Но мы не остановимся на этом. Теперь мы начнем с самого нуля.

Мы реализуем следующий класс для создания итератора в Python для квадратов чисел от 1 до максимального указанного.

class PowTwo:

    def __init__(self, max=0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration

Здесь __init __() принимает значение max. Затем мы создаем объект «a» класса PowTwo с аргументом 4. Затем мы создаем итератор, используя iter(). Далее мы используем функцию next(), чтобы получать элементы один за другим.

a=PowTwo(4)
i=iter(a)
next(i)
1
>>> next(i)
2
>>> next(i)
4
>>> next(i)
8
>>> next(i)
16
>>> next(i)
Traceback (most recent call last):
File “<pyshell#484>”, line 1, in <module>
next(i)
File “<pyshell#476>”, line 13, in __next__
raise StopIteration
StopIteration

В качестве альтернативы вы можете использовать методы __iter __() и __next __() для этого объекта.

j=a.__iter__()
j.__next__()
1
>>> j.__next__()
2
>>> j.__next__()
4
>>> j.__next__()
8
>>> j.__next__()
16
>>> j.__next__()
Traceback (most recent call last):
File “<pyshell#491>”, line 1, in <module>
j.__next__()
File “<pyshell#476>”, line 13, in __next__
raise StopIteration
StopIteration

Функция iter() вызывает метод __iter __() внутри себя.

6. Бесконечный итератор

В Python действительно возможно создать итератор, который никогда не исчерпывается. Функция iter() может принимать другой аргумент, называемый «страж». Этот страж является точкой выхода и работает следующим образом: как только значение, возвращаемое итератором равно значению стража, итератор заканчивается.

Мы знаем, что функция int() без параметра внутри возвращает 0.

>>> int()

Теперь мы вызываем iter() с двумя аргументами — int и 1.

>>> a=iter(int,1)

Этот итератор Python никогда не исчерпает себя, он бесконечен. Это потому, что 0 никогда не равен 1. Серьезно, никогда.

>>> next(a)
>>> next(a)
>>> next(a)
>>> next(a)
>>> next(a)

И так далее.

Чтобы создать бесконечный итератор Python с использованием класса, рассмотрим следующий пример.

class Even:
        def __iter__(self):
            self.num=2
            return self
        def __next__(self):
            num=self.num
            self.num+=2
            return num             
>>> e=Even()
>>> i=iter(e)
>>> next(i)
2
>>> next(i)
4
>>> next(i)
6
>>> next(i)
8

Здесь Python перебирает четные числа, начинающиеся с 2 и никогда не заканчивающиеся. Таким образом, вы должны быть осторожны и обеспечить завершающее условие (точку выхода).

7. Преимущества итераторов языка Python

Итератор в python экономит ресурсы. Чтобы получить все элементы, в памяти одновременно хранится только один элемент. В отличие от итератора, список должен хранить все значения одновременно.

8. Делаем выводы

В этой статье мы узнали об итераторах Python. Разве они не веселые и супер удобные? Итератор использует всего две функции — iter() и next(). Тем не менее, мы можем сделать наш собственный итератор в Python при помощи класса. Наконец, мы рассмотрели также бесконечные итераторы.

Кроме того, если у вас есть какие-либо вопросы/сомнения, не стесняйтесь задавать их в поле для комментариев.