Python Iterators (__iter__ i __next__): Kako ga koristiti i zašto?

Iteratori su objekti koji se mogu ponoviti. U ovom vodiču naučit ćete kako iterator radi i kako možete izgraditi vlastiti iterator pomoću __iter__ i __next__ metoda.

Video: Python Iterators

Iteratori u Pythonu

Iteratori su svugdje u Pythonu. Oni su elegantno implementirani unutar forpetlji, shvaćanja, generatora itd., Ali su skriveni na vidiku.

Iterator u Pythonu jednostavno je objekt na koji se može ponoviti. Objekt koji će vraćati podatke, jedan po jedan element.

Tehnički gledano, Python objekt iteratora mora implementirati dvije posebne metode __iter__()i __next__()zajednički nazvan iterator protokol .

Objekt se naziva iterabilnim ako od njega možemo dobiti iterator. Većina ugrađenih spremnika u Pythonu, poput: popisa, korice, niza itd., Mogu se ponoviti.

iter()Funkcija (što pak poziva __iter__()metodu) vraća Iterator od njih.

Iteriranje kroz iterator

next()Funkciju koristimo za ručno itiriranje kroz sve stavke iteratora. Kad dođemo do kraja i ne bude više podataka za vraćanje, to će pokrenuti StopIterationizuzetak. Slijedi primjer.

 # define a list my_list = (4, 7, 0, 3) # get an iterator using iter() my_iter = iter(my_list) # iterate through it using next() # Output: 4 print(next(my_iter)) # Output: 7 print(next(my_iter)) # next(obj) is same as obj.__next__() # Output: 0 print(my_iter.__next__()) # Output: 3 print(my_iter.__next__()) # This will raise error, no items left next(my_iter)

Izlaz

 4 7 0 3 Traceback (najnoviji zadnji poziv): Datoteka "", redak 24, u sljedećem (my_iter) StopIteration

Elegantniji način automatskog ponavljanja je upotreba for petlje. Koristeći ovo, možemo itirati preko bilo kojeg objekta koji može vratiti iterator, na primjer popis, niz, datoteka itd.

 >>> for element in my_list:… print(element)… 4 7 0 3

Rad petlje for za iteratore

Kao što vidimo u gornjem primjeru, forpetlja je mogla automatski prelaziti kroz popis.

Zapravo se forpetlja može ponoviti preko bilo kojeg iterabila. Pogledajmo bliže kako se forpetlja zapravo implementira u Python.

 for element in iterable: # do something with element

Zapravo se provodi kao.

 # create an iterator object from that iterable iter_obj = iter(iterable) # infinite loop while True: try: # get the next item element = next(iter_obj) # do something with element except StopIteration: # if StopIteration is raised, break from loop break

Dakle, interno, forpetlja stvara objekt iteratora, iter_objpozivajući iter()iterable.

Ironično je da je ova forpetlja zapravo beskonačna while petlja.

Unutar petlje poziva next()da dobije sljedeći element i izvršava tijelo forpetlje s ovom vrijednošću. Nakon što se svi predmeti ispušu, StopIterationpodiže se koji se iznutra hvata i petlja završava. Imajte na umu da će proći bilo koja druga vrsta iznimke.

Izgradnja prilagođenih iteratora

Izgradnja iteratora od nule u Pythonu je jednostavna. Samo moramo provesti __iter__()i na __next__()metode.

__iter__()Metoda vraća sama Iterator objekt. Ako je potrebno, može se izvršiti neka inicijalizacija.

__next__()Metoda mora se vratiti sljedeće stavke u nizu. Kad dođe do kraja i u sljedećim pozivima, mora se povisiti StopIteration.

Ovdje prikazujemo primjer koji će nam dati sljedeći stepen 2 u svakoj iteraciji. Eksponent snage započinje od nule do broja korisnika.

Ako nemate pojma o objektno orijentiranom programiranju, posjetite Python objektno orijentirano programiranje.

 class PowTwo: """Class to implement an iterator of powers of two""" def __init__(self, max=0): self.max = max def __iter__(self): self.n = 0 return self def __next__(self): if self.n <= self.max: result = 2 ** self.n self.n += 1 return result else: raise StopIteration # create an object numbers = PowTwo(3) # create an iterable from the object i = iter(numbers) # Using next to get to the next iterator element print(next(i)) print(next(i)) print(next(i)) print(next(i)) print(next(i))

Izlaz

 1 2 4 8 Traceback (najnoviji zadnji poziv): Datoteka "/home/bsoyuj/Desktop/Untitled-1.py", red 32, u ispisu (sljedeći (i)) Datoteka "", redak 18, u __next__ podići StopIteration StopIteracija

Također možemo koristiti forpetlju za prelazak preko naše iteratorske klase.

 >>> for i in PowTwo(5):… print(i)… 1 2 4 8 16 32

Python beskonačni ponovitelji

Nije potrebno da se stavka u iteratorskom objektu mora iscrpiti. Mogu biti beskonačni iteratori (koji nikad ne završavaju). Moramo biti oprezni pri rukovanju takvim iteratorima.

Evo jednostavnog primjera za demonstriranje beskonačnih iteratora.

Ugrađena funkcija iter()funkcije može se pozvati s dva argumenta, pri čemu prvi argument mora biti objekt koji se može pozvati (funkcija), a drugi je stražar. Iterator poziva ovu funkciju sve dok vraćena vrijednost ne bude jednaka sentinelu.

 >>> int() 0 >>> inf = iter(int,1) >>> next(inf) 0 >>> next(inf) 0

Možemo vidjeti da int()funkcija uvijek vraća 0. Dakle, prosljeđivanjem kao iter(int,1)vratit će se iterator koji poziva int()dok vraćena vrijednost ne bude jednaka 1. To se nikada ne događa i dobivamo beskonačni iterator.

Također možemo izgraditi vlastite beskonačne iteratore. Sljedeći će iterator teoretski vratiti sve neparne brojeve.

 class InfIter: """Infinite iterator to return all odd numbers""" def __iter__(self): self.num = 1 return self def __next__(self): num = self.num self.num += 2 return num

Uzorak bi bio sljedeći.

 >>> a = iter(InfIter()) >>> next(a) 1 >>> next(a) 3 >>> next(a) 5 >>> next(a) 7

I tako dalje…

Pripazite da uključite završno stanje kada prelazite preko ovih vrsta beskonačnih iteratora.

Prednost korištenja iteratora je u tome što štede resurse. Kao što je prikazano gore, mogli bismo dobiti sve neparne brojeve bez pohrane cijelog brojevnog sustava u memoriju. Možemo imati beskonačne predmete (teoretski) u konačnom pamćenju.

Postoji jednostavniji način za stvaranje iteratora u Pythonu. Da biste saznali više, posjetite: Python generatori koji koriste yield.

Zanimljivi članci...