Если вы новичок в программировании, концепции iterable, а также iterators сбивают с толку, как и многих других.

В этом посте я постараюсь прояснить их на некоторых примерах. Итак, давайте начнем.

Итерируемый

Согласно официальной документации Python,

iterable — это объект, способный возвращать свои члены по одному.[1]

Примеры итераций: list, str, tuple, dict, set и т. д.

Рассмотрим, например, строку Python. Поскольку строка представляет собой iterable, мы можем обращаться к ее элементам по одному.

>>> my_string = "Hello World"
>>>
>>> for a_character in my_string:
>>>     print(a_character)
H
e
l
l
o
 
W
o
r
l
d

С другой стороны, такие объекты, как int, float и т. д., не являются iterable. Это означает, что мы не можем получить доступ к отдельным элементам этих объектов по одному.

>>> my_int = 12345
>>> 
>>> for an_int in my_int:  # since 'int' is not iterable, we will get a TypeError
>>>     print(an_int)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [3], line 3
      1 my_int = 12345
----> 3 for an_int in my_int:  # since 'int' is not iterable, we will get an error
      4     print(an_int)

TypeError: 'int' object is not iterable

Мы можем преобразовать iterable в iterator с помощью встроенной функции iter()

Итератор

Итератор, согласно документации python,

Объект, представляющий поток данных. Объект итератора имеет следующие методы[2]

  • __next__() метод, который возвращает следующий элемент в потоке данных
  • __iter__(), который возвращает сам объект итератора.

Например, поскольку list — это iterable, мы можем преобразовать список в iterator следующим образом.

>>> lst = [1, 2, 3]

>>> iterator_lst = iter(lst)
>>> print(next(iterator_lst))
>>> print(next(iterator_lst))
>>> print(next(iterator_lst))
1
2
3

Когда в потоке данных больше нет элементов, вызов метода __next__() приведет к возникновению исключения StopIteration.

Например, сейчас у нас iterator_lst, все элементы в списке исчерпаны. Следовательно, вызов метода __next__() еще раз приведет к исключению StopIteration.

>>> print(next(iterator_lst))  # `StopIteration exception
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In [8], line 1
----> 1 print(next(iterator_lst))

StopIteration: 

Когда мы используем итерации с циклом for, zip(), map() и т. д., где требуется последовательность, мы не хотим явно преобразовывать iterable в iterator с методом __iter__(). Скажем, цикл for сделает это за нас.

Так, например,

Мы знаем, что list — это iterable, поэтому, когда мы используем list, скажем, в цикле for, мы не хотим вызывать метод iter() для list и явно преобразовывать их в iterator. Цикл for позаботится об этом следующим образом.

>>> lst = [1, 3, 5, 7]
>>> 
>>> for ele in lst:  # `for` loop internally, automatically converts the iterable list into an iterator
>>>     print(ele)
1
3
5
7

Мы уже упоминали, что такие объекты, как int, float и т. д., не являются iterables. Это означает, что мы не можем преобразовать их в iterators. По умолчанию эти объекты тоже не iterators. Это означает, что мы не можем вызывать эти объекты как с next(), так и с iter().

например

>>> my_int = 12345  # An integer object
>>> iter(my_int)  #`int` is not iterable. so we cannot convert it into iterator. 
# therefore, this line will generate TypeError
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [12], line 1
----> 1 iter(my_int)

TypeError: 'int' object is not iterable
>>> next(my_int)  # `int` is not iterator. Therefore, this line will throw TypeError
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [13], line 1
----> 1 next(my_int)

TypeError: 'int' object is not an iterator

Таким образом, такие объекты, как int, float и т. д., не являются ни iterables, ни iterators.

Рекомендации

  1. итерируемый: https://docs.python.org/3/glossary.html#term-iterable
  2. итератор: https://docs.python.org/3/glossary.html#term-iterator