Как я уже сказал в комментарии:
При завершении итерации вы должны вызвать исключение StopIteration
, на этом этапе вы уже должны знать, что должны выполнить очистку, иначе этот итератор будет запущен навсегда.
Также итераторы и итерируемые - это разные вещи, от беглого python book:
итератор
Любой объект, который реализует next метод без аргументов, который возвращает следующий элемент в серии или вызывает StopIteration, когда больше нет элементов. Итераторы Python также реализуют метод iter , поэтому они также могут быть повторяемыми
Где:
iterable Любой объект, из которого построена iter- в функции можно получить итератор. Объекты, реализующие метод iter , возвращающий итератор, являются итеративными.
Поэтому итератор должен знать, когда он закончится. Надеемся, этот код прояснит ситуацию:
from random import randint
class MyIterator:
def __init__(self, n):
self.n = n
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i < self.n:
self.i += 1
return randint(1, 10)
else:
print("doing cleanup")
#do the clean up you want
raise StopIteration()
class MyIterable:
def __init__(self, n):
self.n = n
def __iter__(self):
return MyIterator(self.n)
for x in MyIterable(5):
print(x)
Вывод:
4
9
7
5
1
doing cleanup
Примечание: Здесь лучше делать что-то, используя функцию генератора или выражение, но это сделает вещи более различимыми.