В моем предыдущем ответе я написал, как я это сделаю, но вот несколько ответов на то, что на самом деле спросили о __iter__
и __next__
...
Итерируемый
Чтобы объект был итеративным, он должен реализовать метод __iter__
, который должен возвращать итератор.
Вот несколько простых примеров:
class A:
def __iter__(self):
return iter([1, 2, 3])
class B:
def __iter__(self):
yield 'a'
yield 'b'
Их можно повторять:
>>> A().__iter__()
<list_iterator object at 0x00000000029EFD30>
>>> iter(A()) # calls A().__iter__()
<list_iterator object at 0x00000000029EFF28>
>>> list(A()) # calls iter(A) and iterates over it
[1, 2, 3]
>>> list(B()) # calls iter(B) and iterates over it
['a', 'b']
Итератор
Объект, возвращаемый из __iter__
, является итератором.Итератор должен реализовать метод __next__
.
Например:
>>> it = iter(B()) # iterator
>>> it.__next__()
'a'
>>> next(it) # calls it.__next__()
'b'
>>> next(it) # raises StopIteration because there is nothing more
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Пользовательский итератор
class MyIterator:
def __init__(self):
self.value = 5
def __next__(self):
if self.value > 0:
self.value -= 1
return self.value
else:
raise StopIteration()
class MyIterable:
def __iter__(self):
return MyIterator()
>>> list(MyIterable())
[4, 3, 2, 1, 0]
РЕДАКТИРОВАТЬ: Как уже упоминалосьв комментариях итератор должен всегда реализовывать __iter__
, который возвращает self
(как я делал в примерах ниже).Это требование можно прочитать в PEP-0234 и в Документах Python :
Класс, который хочет быть итератором, должен реализовывать два метода: a *Метод 1041 *, который ведет себя так, как описано выше, и метод __iter__()
, который возвращает self
.
итеративный итератор
итеративный итератор?Хорошо, если класс реализует как __iter__
, так и __next__
, то это оба:
class IterableIterator:
def __init__(self):
self.value = 11
def __next__(self):
if self.value < 17:
self.value += 1
return self.value
else:
raise StopIteration()
def __iter__(self):
return self
>>> list(IterableIterator())
[12, 13, 14, 15, 16, 17]
enumerate
enumerate
на самом деле делает что-то вроде этого:
class enumerate:
def __init__(self, iterable, start=0):
self.iterator = iter(iterable)
self.n = start - 1
def __iter__(self):
return self
def __next__(self):
self.n += 1
next_item = next(self.iterator)
return self.n, next_item
Итак, чтобы ответить на ваш вопрос, в вашем super().__next__()
вы вызываете этот __next__
здесь, который использует итератор, который он сохранил в конструкторе.