for
l oop всегда вызывает iter
, чтобы получить итератор для obj1
. Грубо говоря, l oop это то же самое, что
obj_iter = iter(obj1) # obj_iter = obj1.__iter__()
while True:
try:
item = next(obj_iter) # item = obj_iter.__next__()
except StopIteration:
break
print(item)
obj_iter
- это возвращаемое значение obj1.__iter__
(так что obj1
сам).
next(obj_iter)
- это возвращаемое значение obj_iter.__next__()
. Ваш метод __next__
никогда не поднимает StopIteration
; it всегда возвращает какое-то новое значение.
Чтобы продемонстрировать использование StopIteration
, рассмотрим небольшую модификацию, которая создает только конечный поток значений меньше 10:
def __next__(self):
count = self.value
<b>if count >= 10:
raise StopIteration</b>
self.value +=1
return count
Несколько примечаний:
- Экземпляр
Inter
повторяется, потому что __iter__
определено. Итератор - это то, что знает, как создать или получить итератор. - Экземпляр
Inter
является итератором, потому что определено __next__
. Итератор - это то, что знает, как создать следующее значение из итерируемого. - Все типы итераторов можно (и по соглашению) сделать итеративными, определив
__iter__ = lambda self: self
: итератор сам является повторяемым - Однако не все повторяющиеся типы являются итераторами.
list.__iter__
не возвращает список; он возвращает экземпляр list_iterator
. Этот экземпляр сохраняет ссылку на исходный список и поддерживает свое собственное состояние для определения list_iterator.__next__
, которое будет использоваться.