Python atkārtotāji (__iter__ un __next__): kā to izmantot un kāpēc?

Iteratori ir objekti, kurus var atkārtot. Šajā apmācībā jūs uzzināsiet, kā darbojas iterators un kā jūs varat izveidot savu iteratoru, izmantojot metodes __iter__ un __next__.

Video: Python Iterators

Iteratori Pitonā

Iteratori Python ir visur. Tie tiek eleganti ieviesti forcilpās, izpratnē, ģeneratoros utt., Bet ir paslēpti redzamā vietā.

Iterator Python ir vienkārši objekts, par kuru var atkārtot. Objekts, kas atgriezīs datus pa vienam elementam.

Tehniski runājot, Python iteratora objektam ir jāievieš divas īpašas metodes __iter__()un __next__(), kopīgi sauktas par iteratora protokolu .

Objektu sauc par iterējamu, ja no tā varam iegūt iteratoru. Lielākā daļa iebūvēto Python konteineru, piemēram: saraksts, kopa, virkne utt., Ir atkārtojami.

iter()Funkcija (kas savukārt izsauc __iter__()metodi) atgriež iteratorā no tiem.

Iterēšana caur iteratoru

Mēs izmantojam next()funkciju, lai manuāli atkārtotu visus iteratora vienumus. Kad mēs nonāksim līdz beigām un vairs nebūs jāatgriež dati, tas paaugstinās StopIterationIzņēmumu. Šis ir piemērs.

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

Rezultāts

 4 7 0 3 Traceback (pēdējais zvans pēdējais): faila "" 24. rindiņa nākamajā (my_iter) StopIteration

Elegantāks automātiskās atkārtošanas veids ir for for izmantošana. Izmantojot to, mēs varam atkārtot jebkuru objektu, kas var atgriezt iteratoru, piemēram, sarakstu, virkni, failu utt.

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

Iteratoru cilpu apstrāde

Kā redzams iepriekšējā piemērā, forcilpa varēja automātiski atkārtoties, izmantojot sarakstu.

Faktiski forcilpa var atkārtot jebkuru atkārtojamu. Apskatīsim tuvāk, kā forcilpa faktiski tiek ieviesta Python.

 for element in iterable: # do something with element

Faktiski tiek ieviests kā.

 # 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

Tātad iekšēji forcilpa izveido iteratora objektu, iter_objizsaucot iter()iterējamo.

Ironiski, ka šī forcilpa faktiski ir bezgalīga, kamēr cilpa.

Cilpas iekšpusē tā aicina next()iegūt nākamo elementu un izpilda forcilpas ķermeni ar šo vērtību. Pēc visu priekšmetu izplūdes StopIterationtiek pacelts, kas tiek iekšēji noķerts, un cilpa beidzas. Ņemiet vērā, ka tiks izieta jebkura cita veida izņēmums.

Pielāgotu iteratoru veidošana

Iteratora izveidošana no nulles ir vienkārša Python. Mums vienkārši jāievieš __iter__()un __next__()metodes.

__iter__()Metode atgriež iteratorā objektu pati. Ja nepieciešams, var veikt dažas inicializācijas.

__next__()Metode jāatgriežas nākošo vienumu secībā. Kad tiek sasniegts gals un nākamajos zvanos, tam ir jāpaaugstina StopIteration.

Šeit mēs parādīsim piemēru, kas mums dos nākamo 2 koeficientu katrā atkārtojumā. Jaudas eksponents sākas no nulles līdz lietotāja iestatītajam skaitlim.

Ja jums nav ne jausmas par objektorientētu programmēšanu, apmeklējiet Python objektorientēto programmēšanu.

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

Rezultāts

 1 2 4 8 Traceback (pēdējais zvans pēdējais): Fails "/home/bsoyuj/Desktop/Untitled-1.py", 32. rindiņa, drukātā veidā (nākamā (i)) Fails "", 18. rindiņa, __next__ __next__ paaugstina StopIteration StopIteration

Mēs varam arī izmantot forcilpu, lai atkārtotu mūsu iteratoru klasi.

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

Python Infinite Iterators

Nav nepieciešams, lai vienums iteratora objektā būtu izsmelts. Var būt bezgalīgi atkārtotāji (kas nekad nebeidzas). Mums jābūt uzmanīgiem, rīkojoties ar šādiem atkārtotājiem.

Šeit ir vienkāršs piemērs bezgalīgu atkārtotāju demonstrēšanai.

Iebūvēto funkcijas iter()funkciju var izsaukt ar diviem argumentiem, kur pirmajam argumentam jābūt izsaucamam objektam (funkcijai), bet otrajam - kontroluzņēmumam. Atkārtotājs izsauc šo funkciju, līdz atgrieztā vērtība ir vienāda ar sargu.

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

Mēs varam redzēt, ka int()funkcija vienmēr atgriež 0. Tātad, nododot to, iter(int,1)atgriezīsies iterators, kas izsauks, int()līdz atgrieztā vērtība būs vienāda ar 1. Tas nekad nenotiek, un mēs iegūstam bezgalīgu atkārtotāju.

Mēs varam izveidot arī savus bezgalīgos atkārtotājus. Šis atkārtotājs teorētiski atgriezīs visus nepāra skaitļus.

 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

Izlases skrējiens būtu šāds.

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

Un tā tālāk…

Atkārtojot šāda veida bezgalīgos atkārtotājus, piesardzīgi iekļaujiet nosacījumu par pārtraukšanu.

Iteratoru izmantošanas priekšrocība ir tā, ka tie ietaupa resursus. Kā parādīts iepriekš, visus nepāra skaitļus mēs varētu iegūt, nesaglabājot atmiņā visu numuru sistēmu. Mums var būt bezgalīgi objekti (teorētiski) ierobežotā atmiņā.

Ir vienkāršāks veids, kā izveidot atkārtotājus Python. Lai uzzinātu vairāk, apmeklējiet: Python ģeneratori, izmantojot ražu.

Interesanti raksti...