Python Iteratorer (__iter__ och __next__): Hur man använder den och varför?

Iteratorer är föremål som kan itereras på. I den här handledningen lär du dig hur iterator fungerar och hur du kan bygga din egen iterator med __iter__ och __next__ metoder.

Video: Python Iterators

Iteratorer i Python

Iteratorer finns överallt i Python. De är elegant implementerade i foröglor, förståelser, generatorer etc. men är dolda i vanlig syn.

Iterator i Python är helt enkelt ett objekt som kan itereras på. Ett objekt som returnerar data, ett element i taget.

Tekniskt sett måste ett Python iterator-objekt implementera två speciella metoder __iter__()och __next__()kallas kollektivt iteratorprotokollet .

Ett objekt kallas iterabelt om vi kan få en iterator från det. De flesta inbyggda behållare i Python som: lista, tupel, sträng etc. är iterabla.

Den iter()funktion (som i sin tur anropar __iter__()metoden) returnerar en iterator från dem.

Iterera genom en Iterator

Vi använder next()funktionen för att manuellt itera igenom alla objekt i en iterator. När vi når slutet och det inte finns mer data att returnera kommer det att höja StopIterationundantaget. Följande är ett exempel.

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

Produktion

 4 7 0 3 Spårning (senaste samtalet senast): Fil "", rad 24, i nästa (min_iter) StopIteration

Ett mer elegant sätt att automatiskt itera är att använda for-slingan. Med hjälp av detta kan vi itera över alla objekt som kan returnera en iterator, till exempel lista, sträng, fil etc.

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

Arbetar med for loop för Iteratorer

Som vi ser i exemplet ovan kunde forslingan upprepas automatiskt genom listan.

I själva verket kan forslingan iterera över alla iterable. Låt oss titta närmare på hur forslingan faktiskt implementeras i Python.

 for element in iterable: # do something with element

Implementeras faktiskt 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 forskapar slingan ett iteratorobjekt iter_objgenom att anropa iter()det iterabla.

Ironiskt nog är den här forslingan faktiskt en oändlig loop.

Inuti slingan ringer den för next()att hämta nästa element och kör forslingans kropp med detta värde. Efter att alla föremål avgaser StopIterationlyfts upp som fångas internt och öglan slutar. Observera att alla andra undantag kommer att passera.

Bygga anpassade Iteratorer

Att bygga en iterator från grunden är lätt i Python. Vi måste bara implementera __iter__()och __next__()metoderna.

Den __iter__()metod returnerar iterator själva objektet. Vid behov kan viss initialisering utföras.

Den __next__()metoden måste returnera nästa objekt i sekvensen. När det når slutet och i efterföljande samtal måste det höjas StopIteration.

Här visar vi ett exempel som ger oss nästa kraft på 2 i varje iteration. Power exponent börjar från noll upp till ett användaruppsättningsnummer.

Om du inte har någon aning om objektorienterad programmering, besök 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))

Produktion

 1 2 4 8 Spårning (senaste samtalet senast): Fil "/home/bsoyuj/Desktop/Untitled-1.py", rad 32, i tryck (nästa (i)) Fil "", rad 18, i __next__ höja StopIteration StopIteration

Vi kan också använda en forslinga för att iterera över vår iteratorklass.

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

Python Infinite Iterators

Det är inte nödvändigt att objektet i ett iteratorobjekt måste tömmas. Det kan finnas oändliga iteratorer (som aldrig slutar). Vi måste vara försiktiga när vi hanterar sådana iteratorer.

Här är ett enkelt exempel för att visa oändliga iteratorer.

Den inbyggda funktionsfunktionen iter()kan anropas med två argument där det första argumentet måste vara ett anropsbart objekt (funktion) och det andra är vaktpost. Iteratorn anropar denna funktion tills det returnerade värdet är lika med sentinel.

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

Vi kan se att int()funktionen alltid returnerar 0. Om du skickar den som iter(int,1)returnerar en iterator som ringer int()tills det returnerade värdet är lika med 1. Detta händer aldrig och vi får en oändlig iterator.

Vi kan också bygga våra egna oändliga iteratorer. Följande iterator returnerar teoretiskt alla udda siffror.

 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 provkörning skulle vara som följer.

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

Och så vidare…

Var noga med att inkludera ett avslutande tillstånd när du itererar över dessa typer av oändliga iteratorer.

Fördelen med att använda iteratorer är att de sparar resurser. Som visat ovan kan vi få alla udda nummer utan att lagra hela nummersystemet i minnet. Vi kan ha oändliga saker (teoretiskt) i ändligt minne.

Det finns ett enklare sätt att skapa iteratorer i Python. För att lära dig mer besök: Python-generatorer med avkastning.

Intressanta artiklar...