Start | iterator
 

iterator



En iterator är ett objekt (en klass) som ger ifrån sig en serie tal. För att göra detta möjligt, alltså "en serie tal", behövs ett sätt för iteratorn att prata med omgivningen så att den (iteratorn) kan lämna ifrån sig dessa tal. Denna detalj löses genom att man i klassen (iteratorn alltså, eller det som är tänkt att bli en iterator) implementerar __next__ som, precis som det låter, returnerar nästa tal i serien. För att python ska veta att det är en iterator, så att den vet att det finns en __next__ så måste man också implementera __iter__ i klassen.

iterator


Så, ett objekt som kan lämna ifrån sig data på begäran, tex implementerar __next__, är en iterator.

Tekniskt är en class som implementerar __iter__ samt __next__ en iterator i python.

iterable = itererbar


Begrips lättast genom att översätta rakt av, itererbar. Iterera, dvs vandra, gå, ta sig igenom. Ett itererbart objekt är ett objekt som vi kan iterera över. T.ex. en lista. Att vi kan skriva såhär...
for i in [2,3,2,3,2]: print(i)
...är möjligt därför att en lista är itererbar. Det är möjligt iterera över den, vilket vi gör med loopen. Itererar över listan.

en enkel iterator


class enSerieTal: def __iter__(self): self.talet = 1 return self def __next__(self): x = self.talet self.talet += 1 return x massatal = enSerieTal() miniter = iter(massatal) print(next(massatal)) print(next(massatal)) print(next(massatal)) print(next(massatal))
Anropet till iter(massatal) här ovan kommer medföra ett anrop till __iter__(self) vilket medför att self.talet kommer till världen. Det är därför felmeddelandet "self.talet finns inte" uppstår om du skippar iter(massatal). Men nedan fungerar utan att vi gör ett anrop till iter().
class enSerieTal: talet = 1 def __iter__(self): return self def __next__(self): x = self.talet self.talet += 1 return x massatal = enSerieTal() print(next(massatal)) print(next(massatal)) print(next(massatal)) print(next(massatal))
__iter__ behövs som sagt för att python ska fatta att det är en iterator och __next__ behövs för att hämta nästa tal med next.

Ovan iterator startar på 1 och pågår i all evighet. Så den är inte är superbra att använda i en loop. Tja, du kan förstås, men då måste du veta att du får tal i all evighet och att du måste avbryta loopen med break.

För att förhindra att iteratorn fortsätter i all evighet, kan man bygga in ett stop med StopIteration

StopIteration


class enSerieTal: def __init__(self,stop): self.stop = stop self.talet = 1 def __iter__(self): return self def __next__(self): if self.talet <= self.stop: x = self.talet self.talet += 1 return x else: raise StopIteration for i in enSerieTal(10): print(i)
Med start, stop och step
class enSerieTal: def __init__(self,start,stop,step): self.talet = start self.stop = stop self.step = step def __iter__(self): return self def __next__(self): if self.talet <= self.stop: x = self.talet self.talet += self.step return x else: raise StopIteration for i in enSerieTal(1,5,0.5): print(i, end=", ")
Säg att vi, till någonting, behöver göra något med faktorerna bakom något tal...
class faktorisera: def __init__(self,talet): self.talet = talet def __iter__(self): return self def __next__(self): for d in range(2,self.talet+1): if(self.talet%d == 0): self.talet=self.talet//d return d raise StopIteration for i in faktorisera(5000): print(i,end=", ")

Lite frågor

Vilka metoder behöver en klass för att få kalla sig iterator ?
  En __inter__ samt en __net__
  En __iterable__ samt en __init__
  En __iter__ samt en __next__
  En __internet__ samt en __next__
15.799999237061 ms