Python-iterators
Python-iterators
Iterators zijn objecten die kunnen worden herhaald. In deze tutorial leer je hoe iterator werkt en hoe je je eigen iterator kunt bouwen met behulp van de methoden __iter__ en __next__.
Video:Python-iterators
Iterators in Python
Iterators zijn overal in Python. Ze zijn elegant geïmplementeerd binnen for
loops, comprehensies, generators etc. maar zijn in het zicht verborgen.
Iterator in Python is gewoon een object waarop kan worden herhaald. Een object dat gegevens retourneert, één element tegelijk.
Technisch gezien is een Python iterator-object moet twee speciale methoden implementeren, __iter__()
en __next__()
, gezamenlijk het iterator-protocol genoemd .
Een object heet itereerbaar als we er een iterator uit kunnen halen. De meeste ingebouwde containers in Python zoals:list, tuple, string etc. zijn iterables.
De iter()
functie (die op zijn beurt de __iter__()
methode) retourneert een iterator van hen.
Itereren via een iterator
We gebruiken de next()
functie om handmatig alle items van een iterator te doorlopen. Wanneer we het einde bereiken en er geen gegevens meer moeten worden geretourneerd, wordt de StopIteration
. verhoogd Uitzondering. Hieronder volgt een voorbeeld.
# 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)
Uitvoer
4 7 0 3 Traceback (most recent call last): File "<string>", line 24, in <module> next(my_iter) StopIteration
Een elegantere manier om automatisch te itereren is door de for-lus te gebruiken. Hiermee kunnen we elk object herhalen dat een iterator kan retourneren, bijvoorbeeld lijst, tekenreeks, bestand enz.
>>> for element in my_list:
... print(element)
...
4
7
0
3
Werking van for-loop voor Iterators
Zoals we in het bovenstaande voorbeeld zien, is de for
loop kon automatisch door de lijst lopen.
In feite is de for
lus kan itereren over elke iterable. Laten we eens nader bekijken hoe de for
loop is daadwerkelijk geïmplementeerd in Python.
for element in iterable:
# do something with element
Is eigenlijk geïmplementeerd als.
# 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
Dus intern, de for
loop maakt een iterator-object, iter_obj
door iter()
. te bellen op de iterabele.
Ironisch genoeg is deze for
loop is eigenlijk een oneindige while-lus.
Binnen de lus roept het next()
. aan om het volgende element te krijgen en voert de hoofdtekst van de for
. uit lus met deze waarde. Nadat alle items zijn uitgeput, StopIteration
wordt omhoog gebracht die inwendig wordt opgevangen en de lus eindigt. Merk op dat elk ander soort uitzondering zal doorgaan.
Aangepaste iterators bouwen
Een iterator helemaal opnieuw bouwen is eenvoudig in Python. We hoeven alleen de __iter__()
. te implementeren en de __next__()
methoden.
De __iter__()
methode retourneert het iterator-object zelf. Indien nodig kan enige initialisatie worden uitgevoerd.
De __next__()
methode moet het volgende item in de reeks retourneren. Bij het bereiken van het einde, en bij volgende oproepen, moet het StopIteration
. verhogen .
Hier laten we een voorbeeld zien dat ons de volgende macht van 2 geeft in elke iteratie. Machtsexponent begint van nul tot een door de gebruiker ingesteld nummer.
Als je geen idee hebt van objectgeoriënteerd programmeren, ga dan naar Objectgeoriënteerd programmeren in Python.
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))
Uitvoer
1 2 4 8 Traceback (most recent call last): File "/home/bsoyuj/Desktop/Untitled-1.py", line 32, in <module> print(next(i)) File "<string>", line 18, in __next__ raise StopIteration StopIteration
We kunnen ook een for
. gebruiken loop om onze iteratorklasse te herhalen.
>>> for i in PowTwo(5):
... print(i)
...
1
2
4
8
16
32
Python Oneindige Iterators
Het is niet nodig dat het item in een iteratorobject uitgeput is. Er kunnen oneindige iterators zijn (die nooit eindigen). We moeten voorzichtig zijn bij het omgaan met dergelijke iterators.
Hier is een eenvoudig voorbeeld om oneindige iterators te demonstreren.
De ingebouwde functie iter()
kan worden aangeroepen met twee argumenten waarbij het eerste argument een oproepbaar object (functie) moet zijn en het tweede de schildwacht. De iterator roept deze functie aan totdat de geretourneerde waarde gelijk is aan de schildwacht.
>>> int()
0
>>> inf = iter(int,1)
>>> next(inf)
0
>>> next(inf)
0
We kunnen zien dat de int()
functie retourneert altijd 0. Dus geef het door als iter(int,1)
zal een iterator teruggeven die int()
. aanroept totdat de geretourneerde waarde gelijk is aan 1. Dit gebeurt nooit en we krijgen een oneindige iterator.
We kunnen ook onze eigen oneindige iterators bouwen. De volgende iterator zal theoretisch alle oneven getallen teruggeven.
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
Een voorbeeldrun zou als volgt zijn.
>>> a = iter(InfIter())
>>> next(a)
1
>>> next(a)
3
>>> next(a)
5
>>> next(a)
7
En zo verder...
Zorg ervoor dat u een beëindigingsvoorwaarde opneemt bij het herhalen van dit soort oneindige iterators.
Het voordeel van het gebruik van iterators is dat ze resources besparen. Zoals hierboven getoond, kunnen we alle oneven nummers krijgen zonder het hele nummersysteem in het geheugen op te slaan. We kunnen (theoretisch) oneindig veel items hebben in een eindig geheugen.
Er is een eenvoudigere manier om iterators in Python te maken. Ga voor meer informatie naar:Python-generatoren die opbrengst gebruiken.
Python