Iteratori în Python
Gândește-te la un iterator ca la un obiect care conține un set numărabil de valori, pe care le poți parcurge pe rând, câte una, până le-ai trecut în revistă pe toate.
Ceea ce face ca un obiect să fie iterator în Python este o regulă numită protocolul iterator: obiectul trebuie să ofere două metode, __iter__() și __next__().
Iterator vs. iterabil
O listă, un tuplu, un dicționar sau o mulțime este un obiect iterabil: un container care îți poate da un iterator atunci când îi ceri unul.
Ca să ceri unul, transmite containerul funcției încorporate iter():
Exemplu
iter() și next().
Creează un tuplu cu "apple", "banana", "cherry".
Ieșire: program Python complet
mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)
print(next(myit))
print(next(myit))
print(next(myit))
Exemplu
iter() și next().
Afișează fiecare caracter, unul câte unul.
Ieșire: program Python complet
mystr = "banana"
myit = iter(mystr)
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
Parcurgerea unui iterator cu o buclă
O buclă for îți oferă o cale mai scurtă de a parcurge orice obiect iterabil:
Exemplu
Ieșire: program Python complet
mytuple = ("apple", "banana", "cherry")
for x in mytuple:
print(x)
Exemplu
Ieșire: program Python complet
mystr = "banana"
for x in mystr:
print(x)
Crearea unui iterator
Propria ta clasă devine un iterator de îndată ce îi adaugi atât __iter__(), cât și __next__().
Capitolul Python Clase/Obiecte explică __init__(), funcția pe care o are fiecare clasă pentru a pregăti lucrurile în momentul în care este creat un obiect.
__iter__() are un rol asemănător: poate face operații de pregătire, dar valoarea pe care o returnează trebuie să fie întotdeauna chiar obiectul iterator.
Și __next__() poate executa operații, iar fiecare apel trebuie să returneze următorul element din secvență.
Exemplu
MyNumbers care implementează __iter__() și __next__().
Iteratorul returnează numere începând cu 1, crescând cu unu de fiecare dată.
Afișează primele 5 valori folosind next().
Ieșire: program Python complet
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
StopIteration
Nimic nu oprește iteratorul din exemplul anterior: cu suficiente apeluri next() sau într-o buclă for, nu s-ar termina niciodată.
Modul de a-l opri este excepția StopIteration.
Pune în __next__() o condiție care ridică această excepție după ce iterația a rulat de câte ori vrei:
Exemplu
MyNumbers cu __iter__() și __next__() care returnează numerele de la 1 la 20.
Folosește StopIteration pentru a opri după 20 de iterații. Afișează toate valorile folosind o buclă for.
Ieșire: program Python complet
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)