Похоже, вы путаете итераторы и итерируемые . Итераторы имеют метод __iter__
, который возвращает итератор. Итераторы имеют метод __next__
, который возвращает либо следующее значение, либо возвращает StopIteration
. Теперь в python указано , что итераторы также являются итераторами (но не наоборот) и что iter(iterator) is iterator
, поэтому итератор, itr
, должен возвращать только себя из своего метода __iter__
.
Итераторы должны иметь метод __iter__()
, который возвращает сам объект итератора, поэтому каждый итератор также является итеративным и может использоваться в большинстве мест, где принимаются другие итерируемые элементы
В коде:
class MyIter:
def __iter__(self):
return self
def __next__(self):
# actual iterator logic
Если вы хотите создать собственный класс итератора, самый простой способ - наследовать от collections.abc.Iterator
, который, как вы видите, определяет __iter__
, как указано выше (это также подкласс collections.abc.Iterable
) , Тогда все, что вам нужно, это
class MyIter(collections.abc.Iterator):
def __next__(self):
...
Конечно, есть намного более простой способ сделать итератор, и это с функцией генератора
def fib():
a = 1
b = 1
yield a
yield b
while True:
b, a = a + b, b
yield b
list(itertools.takewhile(lambda x: x < 100, fib()))
# --> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Просто для справки, это (упрощенный) код для абстрактного итератора и повторяемый
from abc import ABC, abstractmethod
class Iterable(ABC):
@abstractmethod
def __iter__(self):
'Returns an instance of Iterator'
pass
class Iterator(Iterable, ABC):
@abstractmethod
def __next__(self):
'Return the next item from the iterator. When exhausted, raise StopIteration'
pass
# overloads Iterable.__iter__
def __iter__(self):
return self