Iterator
;Тип iterator
является обобщением понятия последовательности. Объект считается итерируемым, если он физически является последовательностью, либо он является объектом, который воспроизводит по одному результату за раз в контексте инструментов выполнения итераций, таких как цикл for ... in
.
В некотором смысле в категорию итерируемых объектов входят как физические последовательности, это списки, кортежи, диапазоны и т. д. , так и виртуальные последовательности, которые вычисляются по требованию.
Недостаток типа Iterator
состоит в том, что при первом его вызове вычисляются сразу все значения последовательности как физической, так и виртуальной, к тому же все они хранятся в памяти до их исчерпания. Этот недостаток решает тип generator
(генератор).
Чтобы обеспечить поддержку итерации, для объектов контейнера необходимо обязательно определить один метод container.__iter__()
. Этот метод возвращает объект итератора. Объект необходим для поддержки протокола итератора, описанного ниже. Если контейнер поддерживает различные типы итераций, можно предоставить дополнительные методы для конкретного запроса итераторов для этих типов итераций.
Примером объекта, поддерживающего несколько форм итерации, может служить древовидная структура, поддерживающая обход как по ширине, так и по глубине. Метод container.__iter__()
соответствует слоту tp_iter
структуры типа для объектов Python в Python/C API.
Нельзя получить длину итератора функцией len()
;
>>> it = iter([i*i for i in range(10)]) >>> len(it) # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: object of type 'list_iterator' has no len()
Итератор не поддерживает получение элемента по индексу;
>>> it = iter([i*i for i in range(10)]) >>> it[2] # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: 'list_iterator' object is not subscriptable
К итератору нельзя применить обычные операции среза или функцию slice()
. Для этих целей, можно использовать функцию itertools.islice()
модуля itertools
.
>>> it = iter([i*i for i in range(10)]) >>> it[2:5] # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: 'list_iterator' object is not subscriptable >>> import itertools >>> list(itertools.islice(it, 2, 5)) # [49, 64, 81]
После прохождения по итератору, он остается пустым;
>>> it = iter([i*i for i in range(10)]) >>> list(it) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> list(it) # []
Iterator
:Объекты типа Iterator
должны поддерживать следующие два метода, которые вместе образуют протокол итератора :
container.__iter__()
:Метод вернет объект итератора. Это необходимо для того, чтобы разрешить использование контейнеров и итераторов с операторами for
и in
. Метод container.__iter__()
соответствует слоту tp_iter
структуры типа для объектов Python в API-интерфейсе. PyTypeObject.tp_iter
- необязательный указатель на функцию, которая возвращает итератор для объекта. Его присутствие обычно сигнализирует о том, что экземпляры этого типа являются итеративными, хотя последовательности могут быть итерируемыми без этой функции.
container.__next__()
:Метод должен возвращать следующий элемент из контейнера, а если элементы в последовательности закончились, то метод container.__next__()
должен бросить исключение StopIteration
.
Python определяет несколько объектов итератора для поддержки итерации по общим и конкретным типам последовательностей, словарям и другим более специализированным формам. Конкретные типы не важны за пределами их реализации протокола итератора.
Как только метод container.__next__()
итератора вызывает StopIteration
, он должен продолжать вызывать его и при последующих вызовах. Реализации, которые не подчиняются этому свойству, считаются нарушенными.
Для создания объекта типа Iterator
можно воспользоваться встроенной функцией iter()
. По итератору можно двигаться с помощью функции next()
.
Iterator
:class SimpleIterator: def __iter__(self): return self def __init__(self, limit): self.limit = limit self.counter = 0 def __next__(self): if self.counter < self.limit: ret = self.counter self.counter += 1 return ret else: raise StopIteration iters = SimpleIterator(5) # По итератору можно двигаться с помощью функции next() print('Функция next:', next(iters)) print('Функция next:', next(iters)) for i in iters: print('Цикл for ... in: ', i) # Вызовем исключение `StopIteration` # т.к. итерация закончилась в цикле for next(iters) # Функция next: 0 # Функция next: 1 # Цикл for ... in: 2 # Цикл for ... in: 3 # Цикл for ... in: 4 # Traceback (most recent call last): # File "/home/script/Simple-Iterator.py", line 26, in <module> # next(iters) # File "/home/script/Simple-Iterator.py", line 15, in __next__ # raise StopIteration # StopIteration
Понимание того, как работают итераторы и генераторы в языках программирования, это один из первых шагов к освоению последовательной обработки гигантских потоков данных. Трейдинг и технический анализ, это вещи, на которых многие делают целое состояние.