Generator-bezogene Themen in Python

PythonPythonBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Abschnitt werden einige zusätzliche Themen im Zusammenhang mit Generatoren behandelt, darunter Generatorausdrücke und das itertools-Modul.

Generatorausdrücke

Eine Generator-Version einer List Comprehension.

>>> a = [1,2,3,4]
>>> b = (2*x for x in a)
>>> b
<generator object at 0x58760>
>>> for i in b:
...   print(i, end=' ')
...
2 4 6 8
>>>

Unterschiede zu List Comprehensions:

  • Konstruiert keine Liste.
  • Einziges nützliches Ziel ist die Iteration.
  • Einmal verbraucht, kann nicht wiederverwendet werden.

Allgemeine Syntax:

(<expression> for i in s if <conditional>)

Es kann auch als Funktionsargument dienen.

sum(x*x for x in a)

Es kann auf jedes Iterable angewendet werden.

>>> a = [1,2,3,4]
>>> b = (x*x for x in a)
>>> c = (-x for x in b)
>>> for i in c:
...   print(i, end=' ')
...
-1 -4 -9 -16
>>>

Der Hauptgebrauch von Generatorausdrücken liegt in Code, der eine Berechnung auf einer Sequenz durchführt, aber das Ergebnis nur einmal verwendet. Beispielsweise werden alle Kommentare aus einer Datei entfernt.

f = open('somefile.txt')
lines = (line for line in f if not line.startswith('#'))
for line in lines:
  ...
f.close()

Mit Generatoren läuft der Code schneller und verwendet wenig Speicher. Es ist wie ein Filter, der auf einem Stream angewendet wird.

Warum Generatoren?

  • Viele Probleme lassen sich in Bezug auf die Iteration viel deutlicher ausdrücken.
    • Schleifen über eine Sammlung von Elementen und Ausführung einer bestimmten Art von Operation (Suchen, Ersetzen, Modifizieren usw.).
    • Prozessierleitungen können auf eine Vielzahl von Datenverarbeitungsproblemen angewendet werden.
  • Bessere Arbeitsspeicher-Effizienz.
    • Erzeugen nur Werte, wenn sie benötigt werden.
    • Im Gegensatz zur Konstruktion riesiger Listen.
    • Kann auf Streaming-Daten operieren
  • Generatoren ermutigen zur Code-Wiederverwendung
    • Trennt die Iteration vom Code, der die Iteration verwendet
    • Sie können einen Toolbox von interessanten Iterationsfunktionen erstellen und mischen und kombinieren.

itertools-Modul

Das itertools ist ein Bibliotheksmodul mit verschiedenen Funktionen, die dazu dienen, Iterierer/Generatoren zu unterstützen.

itertools.chain(s1,s2)
itertools.count(n)
itertools.cycle(s)
itertools.dropwhile(predicate, s)
itertools.groupby(s)
itertools.ifilter(predicate, s)
itertools.imap(function, s1,... sN)
itertools.repeat(s, n)
itertools.tee(s, ncopies)
itertools.izip(s1,..., sN)

Alle Funktionen verarbeiten die Daten iterativ. Sie implementieren verschiedene Arten von Iterationsmustern.

Weitere Informationen finden Sie im Tutorial Generator Tricks for Systems Programmers von PyCon '08.

In den vorherigen Übungen haben Sie Code geschrieben, der Zeilen verfolgte, die in eine Logdatei geschrieben wurden, und diese in eine Reihe von Zeilen analysierte. In dieser Übung bauen wir darauf fort. Stellen Sie sicher, dass stocksim.py weiterhin läuft.

Übung 6.13: Generatorausdrücke

Generatorausdrücke sind eine Generator-Version einer List Comprehension. Beispielsweise:

>>> nums = [1, 2, 3, 4, 5]
>>> squares = (x*x for x in nums)
>>> squares
<generator object <genexpr> at 0x109207e60>
>>> for n in squares:
...     print(n)
...
1
4
9
16
25

Im Gegensatz zu einer List Comprehension kann ein Generatorausdruck nur einmal verwendet werden. Wenn Sie daher einen weiteren for-Schleifenversuch machen, erhalten Sie nichts:

>>> for n in squares:
...     print(n)
...
>>>

Übung 6.14: Generatorausdrücke in Funktionsargumenten

Generatorausdrücke werden manchmal in Funktionsargumenten eingesetzt. Es sieht zunächst ein wenig seltsam aus, aber versuchen Sie dieses Experiment:

>>> nums = [1,2,3,4,5]
>>> sum([x*x for x in nums])    ## Eine List Comprehension
55
>>> sum(x*x for x in nums)      ## Ein Generatorausdruck
55
>>>

Im obigen Beispiel würde die zweite Version mit Generatoren erheblich weniger Speicher verwenden, wenn es um eine große Liste geht.

In Ihrer portfolio.py-Datei haben Sie einige Berechnungen mit List Comprehensions durchgeführt. Versuchen Sie, diese durch Generatorausdrücke zu ersetzen.

✨ Lösung prüfen und üben

Übung 6.15: Codevereinfachung

Generatorausdrücke sind oft eine nützliche Ersatzmethode für kleine Generatorfunktionen. Beispielsweise anstatt eine Funktion wie diese zu schreiben:

def filter_symbols(rows, names):
    for row in rows:
        if row['name'] in names:
            yield row

Können Sie etwas wie Folgendes schreiben:

rows = (row for row in rows if row['name'] in names)

Ändern Sie das ticker.py-Programm, um Generatorausdrücke an geeigneten Stellen zu verwenden.

✨ Lösung prüfen und üben

Zusammenfassung

Herzlichen Glückwunsch! Sie haben das Lab zu Generatoren abgeschlossen. Sie können in LabEx weitere Labs absolvieren, um Ihre Fähigkeiten zu verbessern.