Seite 1 von 1

Unterscheidung: Generator, Iterator, iter(), next(), __iter__(), __next__()

Verfasst: Donnerstag 17. Juni 2021, 19:11
von GabrielleChanel
Hallo, ich habe etwas ein Durcheinander mit Generator, Iterator, iter(), next(), __iter__() und __next__(). Kann mir jemand bitte Klarheit verschaffen?
Am besten wäre ein Beispiel um diese zwei Fragen zu veranschaulichen, danke :)

1. Was unterscheidet diese beiden voneinander?
<list_iterator object at 0x000001C73...>
<generator object ClassName.__iter__ at 0x000001C73...>

2. iter() und next() können mit ihrer Spezialmethode __iter__() und __next__() "überschrieben" werden. Was ich noch nicht verstehe ist wann muss ich nur __iter__() implementieren und wann muss ich auch noch ein __next__() implementieren?

Re: Unterscheidung: Generator, Iterator, iter(), next(), __iter__(), __next__()

Verfasst: Donnerstag 17. Juni 2021, 19:44
von __blackjack__
@GabrielleChanel: Ad 1. Ein Iterator hat eine `__iter__()`-Methode die einfach nur `self` zurück gibt, und eine `__next__()`-Methode die entweder das nächste Objekt liefert oder `StopIteration` auslöst wenn es kein nächstes Objekt gibt.

Bei einem Generator kommen die Methoden `close()`, `send()`, und `throw()` zu dem was ein Iterator hat noch dazu. Das sollte aber auch irgendwo dokumentiert sein.

Ad 2. Das kommt darauf an. Bei einem Iterator musst Du beides implementieren, so wie in Ad 1 beschrieben. Wenn ein Objekt iterierbar sein soll, dann nur `__iter__()` und das muss einen Iterator liefern. Das kann auch ein Generator sein, denn das ist ja auch ein Iterator. `__next__()` braucht man eher sehr selten, weil es in der Regel einfacher ist entweder eine Generatorfunktion zu schreiben, oder sich was iterierbares aus anderen Werkzeugen (`itertools`, `map()`, `filter()`, `more_itertools`, Generatorausdruck, …) zu basteln statt eine komplette Klasse nur für einen Iterator zu schreiben.

Re: Unterscheidung: Generator, Iterator, iter(), next(), __iter__(), __next__()

Verfasst: Freitag 18. Juni 2021, 09:54
von GabrielleChanel
@__blackjack__ vielen Dank für deine Erläuterungen. Es wird mir nun langsam klarer. Noch eine Frage bezüglich __next__() Methode. Bei dieser Methode geht es darum zu vergleichen, ob noch ein Element übrig ist, wieso verwendet man aber kein len()? Oder sogar ein (len())-1, wenn man kein StopIteration Error will? Ich weiss nicht wie es dann implementiert werden soll, deswegen habe ich hier einen etwas lückenhaften Pseudocode erstellt. Verstehst du meine Frage?

Code: Alles auswählen

...
def __init__(self, max):
    ...

def __iter__(self):
    return self

def __next__(self):
    if self.n <= self.max #ich meine in dieser Zeile statt ein self.max etwas mit len()
    ...

Re: Unterscheidung: Generator, Iterator, iter(), next(), __iter__(), __next__()

Verfasst: Freitag 18. Juni 2021, 10:18
von Sirius3
Einen StopIteration-Error sieht man normalerweise gar nicht, weil der z.B. direkt bei einer for-Schleife intern abgefangen wird.
Für viele Iteratoren kann man gar keine Länge angeben, weil nicht von Anfang an klar ist, wie viele Elemente es gibt.