Python Iterators (__iter__ og __next__): Hvordan bruke den og hvorfor?

Iteratorer er gjenstander som kan gjentas på. I denne opplæringen lærer du hvordan iterator fungerer og hvordan du kan bygge din egen iterator ved hjelp av __iter__ og __next__ metoder.

Video: Python Iterators

Iteratorer i Python

Iteratorer er overalt i Python. De er elegant implementert i forløkker, forståelser, generatorer osv., Men er skjult i vanlig syn.

Iterator i Python er ganske enkelt et objekt som kan gjentas. Et objekt som vil returnere data, ett element om gangen.

Teknisk sett må et Python iterator-objekt implementere to spesielle metoder, __iter__()og __next__()samlet kalt iteratorprotokollen .

Et objekt kalles iterabelt hvis vi kan få en iterator fra det. De fleste innebygde containere i Python som: liste, tuple, streng osv. Er iterables.

Den iter()funksjon (som i sin tur anroper __iter__()metoden) returnerer i en iteratorblokk fra dem.

Iterere gjennom en Iterator

Vi bruker next()funksjonen til å manuelt gjenta alle elementene i en iterator. Når vi når slutten og det ikke er flere data som skal returneres, vil det øke StopIterationunntaket. Følgende er et eksempel.

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

Produksjon

 4 7 0 3 Sporing (siste samtale sist): Fil "", linje 24, i neste (my_iter) StopIteration

En mer elegant måte å automatisk itere på er ved å bruke for loop. Ved å bruke dette kan vi iterere over ethvert objekt som kan returnere en iterator, for eksempel liste, streng, fil etc.

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

Arbeid av for loop for Iterators

Som vi ser i eksemplet ovenfor, var forsløyfen i stand til å gjenta automatisk gjennom listen.

Faktisk kan forsløyfen gjentas over enhver iterabel. La oss se nærmere på hvordan forsløyfen faktisk er implementert i Python.

 for element in iterable: # do something with element

Er faktisk implementert som.

 # 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

Så internt foroppretter sløyfen et iteratorobjekt iter_objved å ringe iter()på iterabelen.

Ironisk nok er denne forsløyfen faktisk en uendelig mens sløyfe.

Inne i løkken ringer den for next()å hente neste element og utfører forsløyfens kropp med denne verdien. Etter at alle elementene eksos, StopIterationheves som er internt fanget og løkken slutter. Merk at alle andre unntak vil passere.

Bygge tilpassede Iteratorer

Det er enkelt å bygge en iterator fra bunnen av i Python. Vi må bare implementere __iter__()og __next__()metodene.

Den __iter__()metoden returnerer iteratoren gjenstanden selv. Om nødvendig kan noen initialisering utføres.

Den __next__()metode må returnere det neste element i sekvensen. Når den når slutten, og i påfølgende samtaler, må den øke StopIteration.

Her viser vi et eksempel som vil gi oss neste kraft på 2 i hver iterasjon. Power exponent starter fra null til et brukerinnstilt nummer.

Hvis du ikke har noen idé om objektorientert programmering, kan du gå til 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))

Produksjon

 1 2 4 8 Traceback (siste samtale sist): Fil "/home/bsoyuj/Desktop/Untitled-1.py", linje 32, i utskrift (neste (i)) Fil "", linje 18, i __next__ heve StopIteration StopIteration

Vi kan også bruke en forsløyfe til å gjenta over iteratorklassen vår.

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

Python Infinite Iterators

Det er ikke nødvendig at gjenstanden i et iteratorobjekt må være oppbrukt. Det kan være uendelige iteratorer (som aldri ender). Vi må være forsiktige når vi håndterer slike iteratorer.

Her er et enkelt eksempel for å demonstrere uendelige iteratorer.

Den innebygde iter()funksjonsfunksjonen kan kalles med to argumenter hvor det første argumentet må være et kallbart objekt (funksjon) og det andre er sentinellen. Iteratoren kaller denne funksjonen til den returnerte verdien er lik sentinellen.

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

Vi kan se at int()funksjonen alltid returnerer 0. Så å sende den som iter(int,1)vil returnere en iterator som ringer int()til den returnerte verdien er lik 1. Dette skjer aldri, og vi får en uendelig iterator.

Vi kan også bygge våre egne uendelige iteratorer. Følgende iterator vil teoretisk returnere alle oddetallene.

 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

En prøvekjøring vil være som følger.

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

Og så videre…

Vær forsiktig med å inkludere en avsluttende tilstand når du gjentar deg over disse typer uendelige iteratorer.

Fordelen med å bruke iteratorer er at de sparer ressurser. Som vist ovenfor, kunne vi få alle oddetallene uten å lagre hele tallsystemet i minnet. Vi kan ha uendelige ting (teoretisk) i endelig minne.

Det er en enklere måte å lage iteratorer i Python på. For å lære mer besøk: Python-generatorer som bruker avkastning.

Interessante artikler...