What are iterator, iterable, and iteration?
What are "iterable", "iterator", and "iteration" in Python? How are they defined?
![]()
![]()
16 Answers 16
Iteration is a general term for taking each item of something, one after another. Any time you use a loop, explicit or implicit, to go over a group of items, that is iteration.
In Python, iterable and iterator have specific meanings.
An iterable is an object that has an __iter__ method which returns an iterator, or which defines a __getitem__ method that can take sequential indexes starting from zero (and raises an IndexError when the indexes are no longer valid). So an iterable is an object that you can get an iterator from.
An iterator is an object with a next (Python 2) or __next__ (Python 3) method.
Whenever you use a for loop, or map , or a list comprehension, etc. in Python, the next method is called automatically to get each item from the iterator, thus going through the process of iteration.
Here’s the explanation I use in teaching Python classes:
- anything that can be looped over (i.e. you can loop over a string or file) or
- anything that can appear on the right-side of a for-loop: for x in iterable: . or
- anything you can call with iter() that will return an ITERATOR: iter(obj) or
- an object that defines __iter__ that returns a fresh ITERATOR, or it may have a __getitem__ method suitable for indexed lookup.
An ITERATOR is an object:
- with state that remembers where it is during iteration,
- with a __next__ method that:
- returns the next value in the iteration
- updates the state to point at the next value
- signals when it is done by raising StopIteration
- The __next__ method in Python 3 is spelt next in Python 2, and
- The builtin function next() calls that method on the object passed to it.

The above answers are great, but as most of what I’ve seen, don’t stress the distinction enough for people like me.
Also, people tend to get «too Pythonic» by putting definitions like «X is an object that has __foo__() method» before. Such definitions are correct—they are based on duck-typing philosophy, but the focus on methods tends to get between when trying to understand the concept in its simplicity.
So I add my version.
In natural language,
- iteration is the process of taking one element at a time in a row of elements.
iterable is an object that is, well, iterable, which simply put, means that it can be used in iteration, e.g. with a for loop. How? By using iterator. I’ll explain below.
. while iterator is an object that defines how to actually do the iteration—specifically what is the next element. That’s why it must have next() method.
Iterators are themselves also iterable, with the distinction that their __iter__() method returns the same object ( self ), regardless of whether or not its items have been consumed by previous calls to next() .
So what does Python interpreter think when it sees for x in obj: statement?
Look, a for loop. Looks like a job for an iterator. Let’s get one. . There’s this obj guy, so let’s ask him.
«Mr. obj , do you have your iterator?» (. calls iter(obj) , which calls obj.__iter__() , which happily hands out a shiny new iterator _i .)
OK, that was easy. Let’s start iterating then. ( x = _i.next() . x = _i.next() . )
Since Mr. obj succeeded in this test (by having certain method returning a valid iterator), we reward him with adjective: you can now call him «iterable Mr. obj «.
However, in simple cases, you don’t normally benefit from having iterator and iterable separately. So you define only one object, which is also its own iterator. (Python does not really care that _i handed out by obj wasn’t all that shiny, but just the obj itself.)
This is why in most examples I’ve seen (and what had been confusing me over and over), you can see:
There are cases, though, when you can benefit from having iterator separated from the iterable, such as when you want to have one row of items, but more «cursors». For example when you want to work with «current» and «forthcoming» elements, you can have separate iterators for both. Or multiple threads pulling from a huge list: each can have its own iterator to traverse over all items. See @Raymond’s and @glglgl’s answers above.
Imagine what you could do:
I’ll repeat again: iterator is not iterable. Iterator cannot be used as a «source» in for loop. What for loop primarily needs is __iter__() (that returns something with next() ).
Of course, for is not the only iteration loop, so above applies to some other constructs as well ( while . ).
Iterator’s next() can throw StopIteration to stop iteration. Does not have to, though, it can iterate forever or use other means.
In the above «thought process», _i does not really exist. I’ve made up that name.
There’s a small change in Python 3.x: next() method (not the built-in) now must be called __next__() . Yes, it should have been like that all along.
You can also think of it like this: iterable has the data, iterator pulls the next item
Disclaimer: I’m not a developer of any Python interpreter, so I don’t really know what the interpreter «thinks». The musings above are solely demonstration of how I understand the topic from other explanations, experiments and real-life experience of a Python newbie.
An iterable is a object which has a __iter__() method. It can possibly iterated over several times, such as list() s and tuple() s.
An iterator is the object which iterates. It is returned by an __iter__() method, returns itself via its own __iter__() method and has a next() method ( __next__() in 3.x).
Iteration is the process of calling this next() resp. __next__() until it raises StopIteration .
Here’s my cheat sheet:
Quiz: Do you see how.
- every iterator is an iterable?
- a container object’s __iter__() method can be implemented as a generator?
- an iterable that has a __next__ method is not necessarily an iterator?
-
Every iterator must have an __iter__ method. Having __iter__ is enough to be an iterable. Therefore every iterator is an iterable.
When __iter__ is called it should return an iterator ( return <iterator> in the diagram above). Calling a generator returns a generator iterator which is a type of iterator.
Here is an example:

I don’t know if it helps anybody but I always like to visualize concepts in my head to better understand them. So as I have a little son I visualize iterable/iterator concept with bricks and white paper.
Suppose we are in the dark room and on the floor we have bricks for my son. Bricks of different size, color, does not matter now. Suppose we have 5 bricks like those. Those 5 bricks can be described as an object – let’s say bricks kit. We can do many things with this bricks kit – can take one and then take second and then third, can change places of bricks, put first brick above the second. We can do many sorts of things with those. Therefore this bricks kit is an iterable object or sequence as we can go through each brick and do something with it. We can only do it like my little son – we can play with one brick at a time. So again I imagine myself this bricks kit to be an iterable.
Now remember that we are in the dark room. Or almost dark. The thing is that we don’t clearly see those bricks, what color they are, what shape etc. So even if we want to do something with them – aka iterate through them – we don’t really know what and how because it is too dark.
What we can do is near to first brick – as element of a bricks kit – we can put a piece of white fluorescent paper in order for us to see where the first brick-element is. And each time we take a brick from a kit, we replace the white piece of paper to a next brick in order to be able to see that in the dark room. This white piece of paper is nothing more than an iterator. It is an object as well. But an object with what we can work and play with elements of our iterable object – bricks kit.
That by the way explains my early mistake when I tried the following in an IDLE and got a TypeError:
List X here was our bricks kit but NOT a white piece of paper. I needed to find an iterator first:
Don’t know if it helps, but it helped me. If someone could confirm/correct visualization of the concept, I would be grateful. It would help me to learn more.
Как создать итератор в Python — Полный обзор генераторов

В данной статье мы рассмотрим способы создания собственных итераторов в Python и какие генераторы лучше всего для этого использовать.
Содержание статьи
Что такое итератор?
Сначала давайте быстро разберемся, что такое итератор. Для более подробного объяснения посмотрите видео «Итератор и итерируемые объекты. Функции iter() и next()» от автора selfedu.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Итерабельный объект представляет собой объект, элементы которого можно перебирать в цикле или иными доступными способами о которых мы поговорим ниже.
Итератор — это объект, который выполняет фактическую итерацию.
Вы можете создать итератор из любого итерабельного объекта, вызвав встроенную функцию iter() :
Вы можете использовать встроенную функцию next для итератора, чтобы получить следующий элемент из него (если элементов больше нет, то вы получите исключение StopIteration ).
Есть еще одно правило об итераторах, которое делает все намного интереснее: итераторы также являются итераторабельными объектами, а их итератор — это они сами.
Зачем нужно создать итератор?
Итераторы позволяют создать итерабельный объект, который перебирает свои элементы по мере выполнения итерации. Это означает, что вы можете создавать ленивые итераторы, которые не определяют следующий элемент, пока вы не попросите их об этом.
Использование итератора вместо списка, множества или другой итерирабельной структуры данных иногда позволяет экономить память. Например, мы можем использовать itertools.repeat для создания итератора, который предоставит нам 100 миллионов четверок ( 4 ):
На моем компьютере этот итератор занимает 56 байт памяти:
Такой же список из 100 миллионов четверок созданный более примитивным способом занимает 762.94 Мб :
Хотя итераторы могут экономить память, они также могут экономить время. Например, если вы хотите вывести только первую строку из 10-гигабайтного файла с логами, вы можете сделать следующее:
Файловые объекты в Python реализованы как итераторы. При итерации по файлу данные считываются в память по одной строке за раз. Если бы вместо этого мы использовали метод readlines для хранения всех строк в памяти, мы могли бы исчерпать всю системную память и убить процесс.
Таким образом, итераторы могут сэкономить память, но иногда они также могут сэкономить и время.
Кроме того, у итераторов есть возможности, которых нет у других итерабельных объектов. Например, их «лень» можно использовать для создания итерабельных объектов неизвестной длины. На самом деле, можно даже создавать бесконечно длинные итераторы.
Например, метод itertools.count создаст нам итератор, который будет выдавать каждое следующее число от 0 до «бесконечности» в зависимости когда вы завершите цикл:
Метод itertools.count по сути является бесконечно длинным итерабельным объектом. И он реализован как итератор.
Объектно-ориентированный итератор
Итак, мы увидели, что итераторы могут экономить память, процессорное время и открывать для нас новые возможности.
Давайте создадим свои собственные итераторы. Для начала мы «изобретем» заново объект итератора itertools.count .
Вот итератор, реализованный с помощью класса:
В этом классе есть конструктор, который инициализирует текущее число итератора на 0 (или то, что было передано в качестве начала из аргумента start ). То, что превращает этот класс в итератора, это наличие методов __iter__ и __next__ .
Когда объект передается встроенной функции str , вызывается метод __str__ . Когда объект передается встроенной функции len , вызывается ее метод __len__ .
- Передав наш объект в функцию iter это приведет к попытке вызвать его метод __iter__ .
- Передав наш объект в функцию next это приведет к попытке вызвать его метод __next__ .
Предполагается, что функция iter возвращает итератор. По этой причине метод __iter__ должен возвращать итератор. Но наш объект сам по себе является итератором, поэтому он должен возвращать самого себя. Объект Count возвращает self из своего метода __iter__ , так как он является собственным итератором.
Функция next должна возвращать следующий элемент в итераторе или вызывать исключение StopIteration , если элементов больше нет. Мы возвращаем текущее число и увеличиваем его на единицу, чтобы оно было больше во время следующего вызова метода __next__ .
Мы можем вручную перебирать объект Count следующим образом:
Мы также можем перебирать объект Count , используя цикл for , как и любой другой итерабельный объект:
Такой объектно-ориентированный подход к созданию итератора — это здорово, но это не типичный способ, которым Python-программисты создают итераторы. Обычно, когда нам нужен итератор, мы создаем генератор.
Генераторы: простой способ создания итератора
Самый простой способ создания собственных итераторов в Python — это создание генератора.
В Python есть два способа создания генераторов.
Дан список чисел:
Мы можем сделать генератор, который будет лениво выдавать все квадраты этих чисел следующим образом:
Или мы можем сделать такой же генератор следующим образом:
Первый подход называется функцией-генератором, а второй — выражением-генератором.
Оба этих объекта-генератора работают одинаково. Они оба имеют тип generator и оба являются итераторами, которые предоставляют квадраты чисел из нашего списка чисел.
Мы поговорим об обоих этих подходах к созданию генератора, но сначала давайте обсудим терминологию.
Слово «генератор» в Python используется в разных смыслах:
- Генератор, также называемый объектом-генератором, — это итератор, тип которого — generator ;
- Функция-генератор — это специальный синтаксис, который позволяет нам создать функцию, возвращающую объект-генератор при вызове;
- Выражение-генератор — это синтаксис, напоминающий представление списков (list comprehension), которое позволяет создавать объект-генератор в одну линию кода.
Убрав эту терминологию, давайте рассмотрим каждую из этих вещей по отдельности. Сначала мы рассмотрим функции-генераторы.
Функции-генераторы
Функции-генераторы отличаются от обычных функций тем, что в них есть один или несколько операторов yield .
Обычно при вызове функции выполняется ее код:
Но если в теле функции есть оператор yield , то это уже не обычная функция. Теперь это функция-генератор, то есть при вызове она возвращает объект-генератор. Этот объект-генератор может выполняться в цикле до тех пор, пока не будет выполнен оператор yield :
Одно только присутствие оператора yield превращает функцию в функцию-генератор. Если вы видите функцию и в ней есть оператор yield , вы работаете с чем-то иным нежели с обычной функцией. Это немного странно, но именно так работают функции-генераторы.
Хорошо, давайте рассмотрим реальный пример функции-генератора. Мы создадим функцию-генератор, которая будет делать то же самое, что и класс-итератор Count , который мы создали ранее.
Подобно классу-итератору Count , мы можем вручную перебирать генератор, полученный в результате вызова функции count :
И мы можем перебирать этот объект генератора с помощью цикла for , как и раньше:
Согласитесь, что данная функция значительно короче и понятнее, чем класс Count , который мы создали ранее.
Выражения-генераторы
Выражения-генераторы — это синтаксис, похожий на синтаксис представления списка (list comprehension), который позволяет нам создать объект-генератор.
Допустим, у нас есть представление-списка, который фильтрует пустые строки из файла и удаляет переход на новую строку в конце \n :
Мы можем создать генератор вместо списка, превратив квадратные скобки в круглые скобки :
Точно так же, как представление списков (list comprehension) вернуло бы нам список, выражение-генератор вернет нам объект-генератор:
Выражения-генераторы используют более короткий синтаксис кода по сравнению с функциями-генераторами. Однако они не такие мощные.
Вы можете написать свою функцию-генератор в такой форме:
Затем вы можете заменить тело функции на выражение-генератор:
Если вы не можете написать свою функцию-генератор в такой форме, то вы не сможете создать выражение-генератор для её замены.
Обратите внимание, что мы изменили используемый пример, потому что мы не можем использовать выражение-генератор для предыдущего примера, который реализует itertools.count который по сути является вечным циклом.
Выражения-генераторы или функции-генераторы?
Выражения-генераторы можно рассматривать как представление-списков (list comprehensions) в мире генераторов.
Если в не знакомы со представлениыем-списков, рекомендую прочитать об этом статью. В этой статье описывается путь от цикла for к list comprehensions.
Также можно скопировать код из функции-генератора и вставить в обычную функцию которая возвращает выражение-генератор:
Выражения-генераторы являются функциями-генераторами так же, как представление-списков являются простым циклом for с добавлением и условием.
Выражения-генераторы очень похожи на представление-списков, их даже можно называть представление-генераторов. Технически это не совсем правильное название, но если вы его произнесете, все поймут, о чем вы говорите.
Нед Батчелдер фактически предложил, чтобы мы все начали называть выражения-генераторы (generator expressions) как представление-генераторов (generator comprehensions), и я склонен согласиться, что это было бы более понятным названием.
Лучший способ создания итератора
Чтобы создать итератор, можно создать класс-итератор, функцию-генератор или выражение-генератор. Но какой способ лучше?
Выражения-генераторы очень лаконичны, но они не такие гибкие, как функции-генераторы. Функции-генераторы гибкие, но если вам нужно добавить дополнительные методы или атрибуты к объекту-итератору, то, скорее всего, придется перейти на использование класса-итератора.
Я бы рекомендовал смотреть в сторону к выражениям-генераторам так же и представление-списков (list comprehensions). Если вы выполняете простую операцию вывода или фильтрации, выражение-генератор — отличное решение. Если вы делаете что-то более сложное, вам, скорее всего, понадобится функция-генератор.
Я бы рекомендовал использовать функции-генераторы так же, как использование цикла for для добавления данных в список. Везде, где требуется метод append , вы зачастую увидите оператор yield вместо него.
И я бы сказал, что класс-итератор лучше не использовать. Если вы обнаружили, что вам нужен класс-итератор, попробуйте написать функцию-генератор, которая делает то, что вам нужно, и посмотрите, как она будет работать в сравнении с классом-итератором.
Генераторы могут помочь при создании итераторов
Вы можете встретить классы-итераторы, но редко попадается хорошая возможность написать свой собственный.
Если создание собственного класса-итератора — редкость, то создание собственного итерабельного класса — не такая уж редкость. Итерабельный класс требует наличия метода __iter__ , который возвращает итератор. Поскольку генераторы — это простой способ создания итератора, мы можем использовать функцию-генератор или выражение-генератор для создания наших методов __iter__ .
Python Iterators
An iterator is an object that contains a countable number of values.
An iterator is an object that can be iterated upon, meaning that you can traverse through all the values.
Technically, in Python, an iterator is an object which implements the iterator protocol, which consist of the methods __iter__() and __next__() .
Iterator vs Iterable
Lists, tuples, dictionaries, and sets are all iterable objects. They are iterable containers which you can get an iterator from.
All these objects have a iter() method which is used to get an iterator:
Example
Return an iterator from a tuple, and print each value:
Even strings are iterable objects, and can return an iterator:
Example
Strings are also iterable objects, containing a sequence of characters:
mystr = "banana"
myit = iter(mystr)Looping Through an Iterator
We can also use a for loop to iterate through an iterable object:
Example
Iterate the values of a tuple:
for x in mytuple:
print(x)Example
Iterate the characters of a string:
for x in mystr:
print(x)The for loop actually creates an iterator object and executes the next() method for each loop.
Create an Iterator
To create an object/class as an iterator you have to implement the methods __iter__() and __next__() to your object.
As you have learned in the Python Classes/Objects chapter, all classes have a function called __init__() , which allows you to do some initializing when the object is being created.
The __iter__() method acts similar, you can do operations (initializing etc.), but must always return the iterator object itself.
The __next__() method also allows you to do operations, and must return the next item in the sequence.
Example
Create an iterator that returns numbers, starting with 1, and each sequence will increase by one (returning 1,2,3,4,5 etc.):
class MyNumbers:
def __iter__(self):
self.a = 1
return selfdef __next__(self):
x = self.a
self.a += 1
return xmyclass = MyNumbers()
myiter = iter(myclass)print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))StopIteration
The example above would continue forever if you had enough next() statements, or if it was used in a for loop.
To prevent the iteration from going on forever, we can use the StopIteration statement.
In the __next__() method, we can add a terminating condition to raise an error if the iteration is done a specified number of times:
Example
Stop after 20 iterations:
class MyNumbers:
def __iter__(self):
self.a = 1
return selfdef __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIterationИтераторы в Python с примерами
Итератор в Python относится к объекту, по которому мы можем выполнять итерацию. iterator состоит из счетных значений, и эти значения можно просматривать одно за другим.
Итератор просто реализует протокол iterator в Python. Протокол итератора – это класс, который имеет два специальных метода, а именно __iter __() и __next __(). С помощью этих двух методов итератор может вычислить следующее значение в итерации.
С итераторами легко работать с последовательностями элементов в Python. Нам не нужно выделять вычислительные ресурсы всем элементам в последовательности, мы выполняем итерацию по одному элементу за раз, что помогает нам сэкономить место в памяти.
В этой статье мы изучим, как работать с итераторами в Python.
Итерируемые объекты
Итерируемый объект – это объект, способный возвращать итератор. Итерируемый объект может представлять, как конечные, так и бесконечные источники данных. Итерация прямо или косвенно реализует два метода: __iter __() и __next __(). Метод __iter __() возвращает объект-итератор, а метод __next __() помогает нам перемещаться по элементам в итеративном объекте.
Примеры итерируемых объектов в Python включают списки, словари, кортежи и наборы.
Создание итератора
В Python мы создаем итератор, реализуя для объекта методы __iter __() и __next __(). Рассмотрим следующий пример:
Мы создали итератор с именем element, который печатает числа от 0 до N. Сначала мы создали экземпляр класса и дали ему имя classinstance. Затем мы вызвали встроенный метод iter() и передали имя экземпляра класса в качестве параметра. Это создает объект-итератор.
Давайте теперь обсудим, как использовать итератор для фактического перебора элементов.
Метод next()
Метод next() помогает нам перебирать элементы итератора. Продемонстрируем это на примере, приведенном выше:
В приведенном выше скрипте мы вызвали метод next() и передали ему имя элемента итератора в качестве параметра. Каждый раз, когда мы это делаем, итератор переходит к следующему элементу в последовательности. Вот еще один пример:
В приведенном выше скрипте мы создали список с именем list1, который содержит 4 целых числа. Создан итератор с именем element. Метод next() помог нам перебрать элементы списка.
Итерация с помощью цикла for
Цикл for помогает нам перебирать любой объект, способный возвращать итератор. Например:
В приведенном выше коде мы создали переменную с именем x, которая используется для перебора элемента итератора через цикл for.
Бесконечные итераторы
Бесконечный итератор – это итератор с бесконечным числом итераций. Мы должны быть особенно осторожны при работе с бесконечными итераторами. Рассмотрим следующий пример:
Приведенный выше код будет работать вечно. Чтобы остановить это, вам придется вмешаться вручную. Вот еще один пример, демонстрирующий, как создать бесконечный итератор в Python:
Код должен возвращать все четные числа, начиная с 0. Мы можем запустить код, как показано ниже:
И эта цепочка может продолжаться вечно. Это показывает, что с бесконечным итератором мы можем иметь бесконечное количество элементов без необходимости хранить их все в памяти.
В следующем разделе мы увидим, как мы можем реализовать механизм выхода из таких бесконечных итераторов.
Остановка итерации
В предыдущем разделе мы увидели, как создать бесконечный итератор в Python. Однако итераторы обычно не предназначены для бесконечных итераций в Python. Всегда удобно реализовать условие завершения.
Мы можем остановить выполнение итератора навсегда с помощью оператора StopIteration. Нам нужно только добавить условие завершения в метод __next __(), которое вызовет ошибку, как только будет достигнуто указанное количество итераций. Вот пример:
Выполнение останавливается после 5 итераций. Это из-за условия self.x <= 5:, добавленного в метод __next __(). Если итератор вызывается после достижения 5, он вызовет событие StopIteration. Рассмотрим пример, приведенный ниже:
Давайте создадим итератор, а затем переберем его:
Условие завершения было реализовано в следующем разделе нашего кода:
Мы передали итератору значение 3, что означает, что итератор не должен выполнять итерацию более 27, то есть 3 ^ 3.
Заключение
Итераторы чрезвычайно полезны, особенно если вам нужно перебрать большую последовательность элементов. Итераторы позволяют выполнять итерацию по последовательности элементов по одному без необходимости загружать все элементы в память сразу.
В этой статье мы увидели, как создавать итераторы в Python и как перебирать элементы в итераторе. Мы также увидели, как создать бесконечный итератор и как добавить условие завершения к бесконечному итератору.