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 for
kilpų, 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 StopIteration
Iš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, for
kilpa galėjo automatiškai kartoti per sąrašą.
Tiesą sakant, for
ciklas gali kartotis per bet kokį pasikartojantį. Pažvelkime atidžiau į tai, kaip for
kilpa 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 for
kilpa sukuria iteratorių objektą, iter_obj
paskambinus iter()
dėl iterable.
Ironiška, bet ši for
kilpa iš tikrųjų yra begalinė, o kilpa.
Kilpos viduje jis kviečia next()
gauti kitą elementą ir vykdo for
kilpos kūną su šia verte. Po visų daiktų išmetimo, StopIteration
yra 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 for
kilpą, 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ų.