Если вы новичок в программировании, концепции 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
.