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 StopIteration
undantaget. 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 for
slingan upprepas automatiskt genom listan.
I själva verket kan for
slingan iterera över alla iterable. Låt oss titta närmare på hur for
slingan 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 for
skapar slingan ett iteratorobjekt iter_obj
genom att anropa iter()
det iterabla.
Ironiskt nog är den här for
slingan faktiskt en oändlig loop.
Inuti slingan ringer den för next()
att hämta nästa element och kör for
slingans kropp med detta värde. Efter att alla föremål avgaser StopIteration
lyfts 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 for
slinga 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.