Python Iterator und Generator

Lassen Sie uns Pythons Iterator und Generator zusammenfassen.

(Ergänzung 2018.12.25: Vollständig durch Python 3-Grammatik ersetzt)

--Iterator: Eine Schnittstelle, über die Sie Elemente iterativ abrufen können (https://docs.python.org/2/library/stdtypes.html#iterator-types). --Generator: Ein Iteratortyp, der jedes Element verarbeitet, wenn es versucht, es abzurufen, und das Element generiert. In Python scheint es, dass es sich häufig auf die Implementierung bezieht, die die Yield-Anweisung verwendet.

Jede in Python integrierte Sammlung (Liste, Tupel, Menge, Diktat usw.) kann iteriert werden. Für die iterative Verarbeitung mit der integrierten Sammlung muss die Sammlung jedoch im Voraus ausgefüllt werden. In den folgenden Fällen: Ich denke, es gibt Fälle, in denen Sie einen Iterator oder Generator selbst implementieren möchten.

Implementierung von Iteratoren nach Klassen

Wenn Sie ein Objekt in einen Kontext einfügen, der einen Iterator erwartet, z. B. "for" in, wird zuerst die Methode "iter ()" des Objekts aufgerufen, sodass eine Iterator-Implementierung zurückgegeben werden muss. Das durch diesen Rückgabewert erhaltene Objekt wird als Methode next () bezeichnet. next () wird aufgerufen, bis Sie eine StopIteration-Ausnahme erhalten.

Es unterscheidet sich nicht von der normalen Liste, ist jedoch ein Beispiel für eine Implementierung, die eine Liste von Zahlen zurückgibt, die zum Zeitpunkt der Instanziierung in der angegebenen Reihenfolge angegeben wurden.

sample1.py


class MyIterator(object):
	def __init__(self, *numbers):
		self._numbers = numbers
		self._i = 0
	def __iter__(self):
		# __next__()Wird von self implementiert, gibt es self so zurück, wie es ist
		return self
	def __next__(self):  #Weiter für Python2(self)Definiert in
		if self._i == len(self._numbers):
			raise StopIteration()
		value = self._numbers[self._i]
		self._i += 1
		return value
        
my_iterator = MyIterator(10, 20, 30)
for num in my_iterator:
	print('hello %d' % num)

Ergebnis ist

hello 10 hello 20 hello 30

Wird sein.

In diesem Beispiel gibt __iter__ () self zurück. Wenn die Verarbeitung für die Iteration jedoch wahrscheinlich kompliziert wird, implementieren Sie eine Implementierungsklasse für die Iteration separat und generieren Sie ein solches Objekt. Es ist auch möglich, es zurückzugeben.

Wenn Sie die integrierte Funktion iter () verwenden, können Sie sehen, dass integrierte Typen wie list ebenfalls nach dieser Regel implementiert werden.

>>> hoge = [1, 2, 3]
>>> hoge_iter = iter(hoge)
>>> hoge_iter.__next__()
1
>>> hoge_iter.__next__()
2
>>> hoge_iter.__next__()
3
>>> hoge_iter.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Iterator Zusammenfassung

Implementierung eines Generators mit Yield

Es mag schwierig sein, den Ertrag zu verstehen, wenn Sie nicht daran gewöhnt sind, aber der Mechanismus ist einfach. Es ist nicht erforderlich, eine Klasse zu definieren, wenn ein Generator mit Yield implementiert wird. Definieren wir die folgende Generatorfunktion.

my_generator.py



def my_generator():
	yield 1
	yield 2
	yield 3

Dies ist ein Generator, der nacheinander drei Werte generiert: "1", "2" und "3". Beachten Sie, dass ** return-Anweisungen nicht in Generatorfunktionen ** verwendet werden können.

Generatoren werden häufig in den folgenden Fällen verwendet, in denen Rechenkosten ein Problem darstellen.

--Kann nicht alle Werte berechnen, die im Voraus wiederholt werden sollen

Eine Generatorfunktion wird durch einen Funktionsaufruf zu einem Iteratorobjekt.

gen = my_generator()
gen.__next__()  # 1
gen.__next__()  # 2
gen.__next__()  # 3
gen.__next__()  # StopIteration

Yield gibt die Kontrolle an die Seite zurück, die next () aufgerufen hat. Lassen Sie uns den Verarbeitungsablauf mit der print-Anweisung überprüfen, wie unten gezeigt.

generator_sample.py



def my_generator():
	print('before yield')
	yield 1
	print('yielded 1')
	yield 2
	print('yielded 2')
	yield 3
	print('yielded 3, finished')

def main():
	gen = my_generator()
	print('start')
	v1 = gen.__next__()
	print('called __next__(), v1=%s' % v1)
	v2 = gen.__next__()
	print('called __next__(), v2=%s' % v2)
	v3 = gen.__next__()
	print('called __next__(), v3=%s' % v3)
	v4 = gen.__next__()  # should be exception

main()

Das Ausführungsergebnis ist wie folgt.

start
before yield
called __next__(), v1=1
yielded 1
called __next__(), v2=2
yielded 2
called __next__(), v3=3
yielded 3, finished
Traceback (most recent call last):
  File "./generator_sample.py", line 21, in <module>
    main()
  File "./generator_sample.py", line 19, in main
    v4 = gen.__next__()  # should be exception
StopIteration

Generatorübersicht

List / Tupel / Set / List-Einschlussnotation und Iterator

Iterierbare können einfach mit integrierten Funktionen wie der Notation Liste / Tupel / Satz / Liste verknüpft werden.

Sie können den obigen einfachen Generator beispielsweise einfach in ein Listenobjekt mit einem Wert wie "[1, 2, 3]" konvertieren, indem Sie ihn an die Funktion "list ()" übergeben. Gleiches gilt für Tupel und Set.


def my_generator():
	yield 1
	yield 2
	yield 3

def my_generator2():
	yield 10
	yield 10
	yield 20

print(list(my_generator()))  # => [1, 2, 3]
print([v * 2 for v in my_generator()])  # => [2, 4, 6]
print(set(my_generator2()))  # => set([10, 20])

Natürlich können nicht nur Generatoren, die mit "Yield" implementiert sind, sondern auch Iteratoren, die mit "next ()" und "Return" implementiert sind, auch mit integrierten Funktionen arbeiten.

itertools

Einführung in Python, da es eine Bibliothek namens [itertools] gibt (https://docs.python.org/ja/3/library/itertools.html), mit der Sie auf einfache Weise verschiedene Vorgänge ausführen können, indem Sie Iter-Objekte kombinieren. Ich werde es verlassen. Ich denke, dies wird hauptsächlich für integrierte Daten wie list / tuple verwendet, ohne einen Iterator selbst zu implementieren. Daher ist es auch dann praktisch, wenn Sie keinen Iterator implementieren.

Zum Beispiel ist es einfach, [alle Kombinationen] von "[1, 2, 3]" und "[" a "," b "] aufzulisten (http://qiita.com/tomotaka_ito/items/5a545423eac654a5b6f5). Ich kann es schaffen

more_itertools

Es gibt auch eine nicht standardmäßige PyPI-Bibliothek namens more_itertools. Es enthält viele nützliche Funktionen, die nicht in itertools enthalten sind. Es gibt "Chunked", das alle N Teile zusammenfasst, und "ilen", das die Zahl durch Drehen des Iterators zählt.

Sie müssen es installieren, um es verwenden zu können.

$ pip install more-itertools

Es gibt auch Qiita-Artikel, der itertools / more_itertools einführt und erklärt, daher denke ich, dass es hilfreich sein wird.

Verwenden Sie den Generator immer und immer wieder

Sobald der Generator in der "for" -Schleife gedreht ist, erscheinen die Elemente nicht in der zweiten und den folgenden "for" -Schleifen.

Wenn Sie die Generatorfunktion beliebig oft ohne Nebenwirkungen aufrufen möchten, Es kann nützlich sein, die in Ich möchte den Python-Generator viele Male wiederholen beschriebene Technik zu verwenden.

Zusammenfassung

Referenzlink

Recommended Posts

Python Iterator und Generator
Python-Listeneinschlussnotation und Generator
[Python] Ein grobes Verständnis von Iterablen, Iteratoren und Generatoren
Generieren Sie Fibonacci-Zahlen mit Python-Closures, Iteratoren und Generatoren
Sehen wir uns die Sprachspezifikationen für Python-Iteratoren und -Generatoren an
[Python] Komprimieren und dekomprimieren
Python- und Numpy-Tipps
[Python] Pip und Wheel
Python-Pakete und -Module
Vue-Cli- und Python-Integration
Ruby, Python und Map
Python-Eingabe und Ausgabe
Python und Ruby teilen sich
Python asyncio und ContextVar
Programmieren mit Python und Tkinter
Ver- und Entschlüsselung mit Python
Python: Klassen- und Instanzvariablen
3-3, Python-Zeichenfolge und Zeichencode
Python 2-Serie und 3-Serie (Anaconda Edition)
Python auf Ruby und wütend Ruby auf Python
Python-Einzug und String-Format
Python Real Number Division (/) und Integer Division (//)
Installieren Sie Python und Flask (Windows 10)
Informationen zu Python-Objekten und -Klassen
Informationen zu Python-Variablen und -Objekten
Apache mod_auth_tkt und Python AuthTkt
Å (Ongustorome) und NFC @ Python
Lernen Sie Python-Pakete und -Module kennen
# 2 [python3] Trennung und Kommentar aus
Flache Python-Kopie und tiefe Kopie
Python und Ruby Slice Memo
Python-Installation und grundlegende Grammatik
Ich habe Java und Python verglichen!
Flache Python-Kopie und tiefe Kopie
Über Python, len () und randint ()
Informationen zu Python-Datums- und Zeitzone
Installieren Sie Python 3.7 und Django 3.0 (CentOS)
Python-Umgebungskonstruktion und TensorFlow
Python-Klassen- und Instanzvariablen
Ruby- und Python-Syntax ~ branch ~
[Python] Python und Sicherheit - is Was ist Python?
Stapel und Warteschlange in Python
Python-Metaklasse und SQLalchemie deklarativ
Implementierung von Fibonacci und Primzahlen (Python)
Python-Grundlagen: Bedingungen und Iterationen
Python-Bitoperator und logische Summe
Python-Debug- und Testmodul
Python-Liste und Tapples und Kommas
Python-Variablen und Objekt-IDs
Über Python und reguläre Ausdrücke
Python mit Pyenv und Venv
Unittest und CI in Python
Maxout Beschreibung und Implementierung (Python)
[Python] Quotient und Überschuss erhalten
Python 3 Sortier- und Vergleichsfunktionen
[Python] Suche nach Tiefenpriorität und Suche nach Breitenpriorität
Identität und Äquivalenz: ist und == in Python
Quellinstallation und Installation von Python
Python oder und und Operatorfalle