W Pythonie iteratory to obiekty, które implementują protokół iteratora: metody __iter__() i __next__(). Iteratory zarządzają swoim wewnętrznym stanem i przy każdym wywołaniu next() zwracają następny element sekwencji lub podnoszą wyjątek StopIteration na końcu.
Obiekty iterowalne to te, po których można przechodzić w pętli (na przykład listy, ciągi, słowniki). Wszystkie mają metodę __iter__(), która zwraca iterator.
Aby zaimplementować własny iterator, należy stworzyć klasę z metodami __iter__() (zwraca self) i __next__() (implementuje logikę pobierania następnego elementu):
class Counter: def __init__(self, low, high): self.current = low self.high = high def __iter__(self): return self def __next__(self): if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 for num in Counter(1, 3): print(num) # 1 2 3
Jaka jest różnica między obiektami iterowalnymi a iteratorami? Czy można iterować po iteratorze więcej niż raz?
Odpowiedź: Obiekt iterowalny implementuje tylko metodę __iter__(), która zwraca iterator. Iterator to obiekt, który ma metodę __next__(). Iterator zazwyczaj można iterować tylko raz: po osiągnięciu końca sekwencji ponowna iteracja nie jest możliwa bez utworzenia nowego iteratora.
Historia
Na projekcie do analizy logów programista napisał funkcję, która przyjmowała iterator i dwukrotnie próbowała po nim przejść (
for log in logs:), oczekując, że oba przejścia dadzą te same wyniki. Druga iteracja nic nie zwracała, ponieważ iterator był już "wykorzystany".
Historia
W jednym z modułów programista zwrócił z funkcji nie listę, a generator, który umożliwiał jednokrotną iterację. Przy próbie przekazania go do innej funkcji, która oczekiwała obiektu iterowalnego do wielu przejść, wystąpił nieoczekiwany błąd i pusty wynik.
Historia
W projekcie Web API programista próbował zserializować iterator bezpośrednio do JSON. Iteratory nie są listami, a konwersja nie jest możliwa bez wcześniejszego przekształcenia do listy (w przeciwnym razie serializacja zakończy się wyjątkiem).