Heim >Backend-Entwicklung >Python-Tutorial >Python-Iteratoren verstehen

Python-Iteratoren verstehen

黄舟
黄舟Original
2016-12-16 11:38:481059Durchsuche

Was ist Iteration?

Objekte, die direkt in for-Schleifen verwendet werden können, werden zusammenfassend als iterierbare Objekte (Iterable) bezeichnet.
Ein Objekt, das von der Funktion next() aufgerufen werden kann und kontinuierlich den nächsten Wert zurückgibt, wird als Iterator bezeichnet.
Alle Iterables können über die integrierte Funktion iter() in Iteratoren umgewandelt werden.

Für Iteratoren reicht ein __next__(). Wenn Sie die for- und in-Anweisungen verwenden, ruft das Programm automatisch das Iteratorobjekt des zu verarbeitenden Objekts auf und verwendet dann seine Methode __next__(), bis eine StopIteration-Ausnahme erkannt wird.

>>> L = [1,2,3]
>>> [x**2 für x in L]
[1, 4, 9]
>>> next(L)
Traceback (letzter Aufruf zuletzt):
Datei „“, Zeile 1, in
TypeError: 'list ' Objekt ist kein Iterator
>>> I=iter(L)
>>> next(I)
>>> )
2
>>> next(I)
3
>>> next(I)
Traceback (letzter Anruf zuletzt):
Datei „“, Zeile 1, in
StopIteration

Im obigen Beispiel kann die Liste L in einer Schleife durchlaufen werden, kann aber nicht mit der integrierten Funktion durchsucht werden Funktion next() Der nächste Wert, also ist L ein Iterable.

L wird von Iter gepackt und auf I gesetzt. I kann von next() verwendet werden, um den nächsten Wert zu finden, also ist I ein Iterator.

Exkurs:

Die eingebaute Funktion iter() ruft nur die __iter__()-Methode des Objekts auf, daher muss es eine Methode __iter__() innerhalb des Listenobjekts geben


Die integrierte Funktion next() ruft nur die Methode __next__() des Objekts auf, daher darf die Methode __next__() nicht innerhalb des Listenobjekts vorhanden sein, diese Methode muss jedoch in Itrator vorhanden sein.


Tatsächlich wird innerhalb der for-Schleife zuerst iter() aufgerufen, um Iterable in Iterator vor der Schleifeniteration umzuwandeln.

>>> L = [4,5,6]

>>> I = L.__iter__()
>>> )
Traceback (letzter Aufruf zuletzt):
Datei „“, Zeile 1, in
AttributeError: „list“-Objekt hat kein Attribut „__next__“
> ;>> I.__next_()
4
>>> >>>> isinstance(L, Iterator)
False
>>> isinstance(I, Iterable)
True
>>> )
True
>>> [x**2 für x in I]
[25, 36]


Iterator erbt von Iterable, aus dem folgenden Test Es ist leicht zu erkennen, dass Iterator die Methoden __iter__() und __next__() enthält, während Iteratble nur __iter__() enthält.

>>> aus Sammlungen importieren Iterator, Iterable

>>> Hilfe (Iterator)

Hilfe zum Klassen-Iterator:

Klasse Iterator(Iterable)
|. Reihenfolge der Methodenauflösung:
|. Iterable
|**Hinweis: Hier ist zu erkennen, dass Iterable von Objekt erbt und Iterator von Iterable .
|. Hier definierte Methoden:
|
|. __iter__(self)
| 🎜>......
>>> help(Iterable)
Hilfe zur Klasse Iterable:

class Iterable(builtins.object)
|.
|
|. __iter__(self)
......


iterable muss die Methode __iter__() enthalten, um den Iterator zurückzugeben, und der Iterator muss _ enthalten Die Methode _next__() wird zum Schleifen verwendet.

Wenn wir den Iterator selbst definieren, reicht es aus, eine Funktion __iter__() in der Klasse zu definieren und sie zu verwenden, um ein Objekt mit der Methode __next__() zurückzugeben.
Gehe direkt zum Code

class Iterable:
def __iter__(self):
return Iterator()

class Iterator:

def __init__(self) :

self.start=-1
def __next__(self):

self.start +=2

if self.start >10:
raise StopIteration
return self. start

I = Iterable()
für i in I: PRint(i)

Der obige Code dient dazu, ungerade Zahlen innerhalb von 10 zu finden. Der Klassenname im Code kann zufällig ausgewählt werden. Es ist nicht erforderlich, den oben angegebenen Klassennamen zu verwenden.
Wenn die StopIteration-Ausnahme nicht in der __next__-Methode von Iterator implementiert ist, dann werden alle ungeraden Zahlen dargestellt, dann müssen beim Aufruf die Bedingungen zum Verlassen der Schleife festgelegt werden.

class Iterable:
def __iter__(self):
return Iterator()

class Iterator:
def __init__(self):
self.start= -1
def __next__(self):
self.start +=2
return self.start

I = Iterable()
for count, i in zip(range( 5),I): #Sie können auch die integrierte Funktion enumerate verwenden, um Zählarbeiten zu implementieren.
print(i)

Wir verwenden den Bereich, um zu erkennen, wie viele Elemente gedruckt werden sollen. Hier bedeutet dies, dass 5 Elemente gedruckt werden, und das Rückgabeergebnis stimmt mit dem oben Gesagten überein.

Natürlich können wir diese beiden Klassen zusammenführen, um das Programm zu vereinfachen.
Die endgültige Version lautet wie folgt:

class Iterable:
def __iter__(self):
return self
def __init__(self):
self.start=-1
def __next__(self):
self.start +=2
if self.start >10:
StopIteration erhöhen
return self.start

I = Iterable ()
für i in I:
print(i)

Iterator kopieren

Iterator ist ein einmaliges Verbrauchsmaterial und wird nach Gebrauch leer sein, siehe .

>>> L=[1,2,3]
>>> für i in I:
... print(i, end='-')
...
1-2-3-
>>>next(I)
Traceback (most letzter Aufruf zuletzt):
Datei „“, Zeile 1, in
StopIteration

Wenn die Schleife erschöpft ist, wird sie erneut aufgerufen. Löst a aus StopIteration-Ausnahme.

Wir möchten den Iterator durch direkte Zuweisung speichern, damit er beim nächsten Mal verwendet werden kann.

Aber wie Sie anhand des Beispiels unten sehen können, funktioniert es überhaupt nicht.

>>> I=iter(L)

>>> J=I
>>> next(I)
>>> next(J)
2
>>> next(I)
>>> next(J)
Traceback (most letzter Aufruf zuletzt):
Datei „“, Zeile 1, in
StopIteration


Wie können wir also den gewünschten Effekt erzielen?
Wir müssen Deepcopy im Kopierpaket verwenden, siehe unten:

>>> import copy
>>> ;>> J=copy.deepcopy(I)

>>> next(I)

>>> next(I)
>>> next(J)
1


Ergänzung: Der Iterator kann sich nicht rückwärts bewegen oder zum Anfang zurückkehren.
Es muss also etwas Besonderes getan werden, um Funktionen wie die Rückwärtsbewegung zu erreichen.

Die oben genannten Codes wurden in Python 3.4 getestet.

Das Obige ist der Inhalt des Verständnisses der Python-Iteratoren. Weitere verwandte Artikel finden Sie auf der chinesischen PHP-Website (www.php.cn).


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn