„Python Iterators“ (__iter__ ir __next__): kaip jį naudoti ir kodėl?

Iteratoriai yra objektai, kuriuos galima kartoti. Šioje pamokoje sužinosite, kaip veikia iteratorius ir kaip galite sukurti savo iteratorių naudodami __iter__ ir __next__ metodus.

Vaizdo įrašas: „Python Iterators“

Iteratoriai „Python“

Iteratoriai yra visur „Python“. Jie elegantiškai įgyvendinami forkilpų, supratimo, generatorių ir kt. Ribose, tačiau yra paslėpti akivaizdoje.

„Iterator Python“ yra tiesiog objektas, kurį galima pakartoti. Objektas, kuris grąžins duomenis po vieną elementą.

Techniškai kalbant, „Python“ iteratoriaus objektas turi įgyvendinti du specialius metodus __iter__()ir __next__()bendrai vadinamą iteratoriaus protokolu .

Objektas vadinamas iteruojamu, jei iš jo galime gauti iteratorių. Dauguma įmontuotų „Python“ talpyklų yra: „list“, „tuple“, „string“ ir kt.

iter()Funkcija (kuri savo ruožtu iškviečia __iter__()metodą) grąžina iteratorių iš jų.

Kartojimas per iteratorių

Mes naudojame next()funkciją rankiniu būdu kartoti visus iteratoriaus elementus. Kai pasieksime pabaigą ir nebebus grąžintinų duomenų, tai padidins StopIterationIšimtį. Toliau pateikiamas pavyzdys.

 # 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)

Rezultatas

 4 7 0 3 „Traceback“ (paskutinis paskutinis skambutis): „“ failas, 24 eilutė, kitoje (my_iter) StopIteration

Elegantiškesnis automatinio kartojimo būdas yra „for“ ciklo naudojimas. Tai naudodami galime kartoti objektą, kuris gali grąžinti iteratorių, pvz., Sąrašą, eilutę, failą ir pan.

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

Iteratorių ciklo darbas

Kaip matome aukščiau pateiktame pavyzdyje, forkilpa galėjo automatiškai kartoti per sąrašą.

Tiesą sakant, forciklas gali kartotis per bet kokį pasikartojantį. Pažvelkime atidžiau į tai, kaip forkilpa iš tikrųjų įgyvendinama „Python“.

 for element in iterable: # do something with element

Faktiškai įgyvendinamas kaip.

 # 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

Taigi Viduje forkilpa sukuria iteratorių objektą, iter_objpaskambinus iter()dėl iterable.

Ironiška, bet ši forkilpa iš tikrųjų yra begalinė, o kilpa.

Kilpos viduje jis kviečia next()gauti kitą elementą ir vykdo forkilpos kūną su šia verte. Po visų daiktų išmetimo, StopIterationyra pakeltas, kuris yra viduje sugautas ir kilpa baigiasi. Atminkite, kad praeis bet kokia kita išimtis.

Individualių iteratorių statyba

„Python“ lengva sukurti iteratorių nuo nulio. Mes tiesiog turime įgyvendinti __iter__()ir __next__()metodus.

__iter__()Metodas grąžina iteratoriaus objektą pati. Jei reikia, galima atlikti tam tikrą inicijavimą.

__next__()Metodas turi grąžinti kitą elementą iš eilės. Pasiekęs pabaigą ir paskesniuose skambučiuose jis turi pakelti StopIteration.

Čia mes parodome pavyzdį, kuris suteiks mums kitą 2 jėgą kiekvienoje iteracijoje. Galios rodiklis prasideda nuo nulio iki vartotojo nustatyto skaičiaus.

Jei neturite idėjos apie objektinį programavimą, apsilankykite „Python Object-Oriented Programming“.

 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))

Rezultatas

 1 2 4 8 „Traceback“ (paskutinis paskutinis skambutis paskutinis): failas „/home/bsoyuj/Desktop/Untitled-1.py“, 32 eilutė, atspausdinta (kitas (i) failas "", 18 eilutė, __next__ pakelti StopIteration StopIteration

Mes taip pat galime naudoti forkilpą, norėdami kartoti iteratorių klasę.

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

„Python“ begaliniai kartotojai

Nebūtina, kad iteratoriaus objekte esantis elementas būtų išeikvotas. Gali būti begalinis kartotojas (kuris niekada nesibaigia). Turime būti atsargūs tvarkydami tokius iteratorius.

Čia yra paprastas pavyzdys, kaip parodyti begalinius kartotojus.

Integruotą funkcijos iter()funkciją galima iškviesti dviem argumentais, kur pirmasis argumentas turi būti iškviečiamas objektas (funkcija), o antrasis yra sargybinis. Kartotojas šią funkciją iškviečia tol, kol grąžinta vertė bus lygi sargybai.

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

Matome, kad int()funkcija visada grąžina 0. Taigi ją iter(int,1)perdavus bus grąžintas iteratorius, kuris skambins int()tol, kol grąžinama reikšmė bus lygi 1. Tai niekada neįvyksta ir gauname begalinį iteratorių.

Mes taip pat galime sukurti savo begalinius iteratorius. Šis iteratorius teoriškai grąžins visus nelyginius skaičius.

 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

Pavyzdinis bandymas būtų toks.

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

Ir taip toliau…

Kartodami šių tipų begalinius kartotojus, atsargiai įtraukite nutraukimo sąlygą.

Iteratorių naudojimo pranašumas yra tas, kad jie taupo išteklius. Kaip parodyta aukščiau, visus nelyginius skaičius galėtume gauti neišsaugoję atmintyje visos skaičių sistemos. Galutinėje atmintyje galime turėti begalę elementų (teoriškai).

Yra lengvesnis būdas sukurti iteratorius „Python“. Norėdami sužinoti daugiau, apsilankykite: „Python“ generatoriai, naudojant derlių.

Įdomios straipsniai...