Source: Python iterators
← Renderedmarkdown source:
---
description: Как сделать итератор в python
tags: python-standart-library python
title: Python iterators
---
Итераторы в python реализуют метод `__iter__` и могут реализовать метод `__next__`. `__iter__` должен всегда возвращать `self`, а `__next__` может возвращать некое значение.
В данном примере мы получаем бесконечный итератор, который возвращает порядковый номер итерации
```python
>>> class Count:
... def __iter__(self):
... self.count = 1
... return self
... def __next__(self):
... x = self.count
... self.count += 1
... return x
>>> c = Count()
>>> count = iter(c)
>>> print(next(count))
1
>>> print(next(count))
2
```
Встроенные функции `next()` и `iter()` позволяют получить итератор и извлечь значение. В цикле `for..if` это происходит неявно:
```python
>>> for i in c:
>>> if i < 10:
>>> print(i)
1
...
9
```
В данном случае итератор был создан заново. Обратите внимание на условие, которое пришлось задать в цикле - без этого условия нам бы пришлось упереться в бесконечную итерацию. Чтобы решить эту логическую проблему, метод `__next__` может поднимать исключение, если мы достигли граничного условия. Перепишем пример:
```python
>>> class Count:
... def __iter__(self):
... self.count = 1
... return self
... def __next__(self):
... x = self.count
... if count < 10:
... self.count += 1
... return x
... else:
... raise StopIteration
>>> c = Count()
>>> for i in c:
>>> print(i)
1
...
9
```
Отлично, итератор остановился там где надо, к тому же `for...in` самостяотельно обработал исключение. Если же мы попробуем сделать это через `next()`, то вот что будет:
```python
...
8
>>> print(next(count))
9
>>> print(next(count))
Traceback (most recent call last):
...
StopIteration
```
Более сложные итераторы могут уметь возвращать себя в виде списка, иметь длину и т.д. Смотри [подробности тут](https://docs.python.org/3/reference/datamodel.html#emulating-container-types)
Основное преимущество итераторов - они вычисляют значения по запросу. Таким образом не требуется вычислит ьвсю последовательность или отображение сразу, что экономит память.
Чтобы облегчить страдания программистов, в python добавлен синтаксис `yield`, который превращает функцию в генератор, возвращающий итератор генератора. В отличие от обычной функции с `return`, которая имеет одну точку входа и после возвращения значения забывает свое состояние, такой итератор будет помнить последнее состояние и при каждом вызове возобновлять работу с той точки, в которой остановился. Подробнее смотри тут: [[python-datamodel]]. Для асинхронных вызовов реализованы исинхронные генераторы через `__aiter__` и `__anext__`.
Смотри еще:
- [[python-glossary]]
- [[python-datamodel]]
- [[python-standart-library]]
- [[asyncio]]
[python-datamodel]: ../lists/python-datamodel "Python datamodel"
[python-glossary]: python-glossary "Python glossary"
[python-standart-library]: ../lists/python-standart-library "Стандартная библиотека python и полезные ресурсы"
[asyncio]: asyncio "Asyncio"