Wann sollte man in Python Generatorausdrücke und wann Listenauflösungen verwenden?
# Generator expression
(x*2 for x in range(256))
# List comprehension
[x*2 for x in range(256)]
Wann sollte man in Python Generatorausdrücke und wann Listenauflösungen verwenden?
# Generator expression
(x*2 for x in range(256))
# List comprehension
[x*2 for x in range(256)]
Bei der Erstellung eines Generators aus einem veränderlichen Objekt (z. B. einer Liste) ist zu beachten, dass der Generator auf der Grundlage des Zustands der Liste zum Zeitpunkt der Verwendung des Generators und nicht zum Zeitpunkt der Erstellung des Generators bewertet wird:
>>> mylist = ["a", "b", "c"]
>>> gen = (elem + "1" for elem in mylist)
>>> mylist.clear()
>>> for x in gen: print (x)
# nothing
Wenn die Möglichkeit besteht, dass die Liste (oder ein veränderbares Objekt innerhalb der Liste) geändert wird, Sie aber den Zustand bei der Erstellung des Generators benötigen, müssen Sie stattdessen ein Listenverständnis verwenden.
Python 3.7:
Listenauffassungen sind schneller.
Generatoren sind speichereffizienter.
Wie alle anderen schon sagten, wenn Sie unendlich viele Daten skalieren wollen, brauchen Sie irgendwann einen Generator. Für relativ statische kleine und mittelgroße Aufgaben, bei denen es auf Geschwindigkeit ankommt, ist eine Listenverarbeitung am besten geeignet.
Manchmal kann man sich mit dem Abschlag Funktion von itertools gibt er mehrere Iteratoren für denselben Generator zurück, die unabhängig voneinander verwendet werden können.
Ich benutze die Hadoop-Hackfleisch-Modul . Ich denke, dies ist ein großartiges Beispiel, das man zur Kenntnis nehmen sollte:
import mincemeat
def mapfn(k,v):
for w in v:
yield 'sum',w
#yield 'count',1
def reducefn(k,v):
r1=sum(v)
r2=len(v)
print r2
m=r1/r2
std=0
for i in range(r2):
std+=pow(abs(v[i]-m),2)
res=pow((std/r2),0.5)
return r1,r2,res
Hier holt der Generator Zahlen aus einer Textdatei (die bis zu 15 GB groß ist) und wendet auf diese Zahlen mithilfe von Hadoops map-reduce einfache Mathematik an. Hätte ich nicht die Yield-Funktion, sondern ein Listenverständnis verwendet, hätte die Berechnung der Summen und des Durchschnitts viel länger gedauert (ganz zu schweigen von der Raumkomplexität).
Hadoop ist ein hervorragendes Beispiel für die Nutzung aller Vorteile von Generatoren.
Listenauffassungen sind eifrig, aber Generatoren sind träge.
In Listenauffassungen werden alle Objekte sofort erstellt, es dauert länger, die Liste zu erstellen und zurückzugeben. In Generatorausdrücken wird die Objekterzeugung verzögert, bis die Anfrage von next()
. Unter next()
Generatorobjekt wird erstellt und sofort zurückgegeben.
Die Iteration ist bei Listenauflösungen schneller, da die Objekte bereits erstellt sind.
Wenn Sie alle Elemente im Listenverständnis und im Generatorausdruck iterieren, ist die Zeitleistung ungefähr gleich. Auch wenn der Generatorausdruck sofort ein Generatorobjekt zurückgibt, werden nicht alle Elemente erstellt. Jedes Mal, wenn Sie über ein neues Element iterieren, wird es erstellt und zurückgegeben.
Wenn man aber nicht alle Elemente durchläuft, ist der Generator effizienter. Nehmen wir an, Sie müssen eine Liste erstellen, die Millionen von Elementen enthält, aber Sie verwenden nur 10 von ihnen. Sie müssen immer noch Millionen von Elementen erstellen. Sie verschwenden nur Zeit für Millionen von Berechnungen, um Millionen von Elementen zu erstellen und nur 10 zu verwenden. Oder wenn Sie Millionen von Api-Anfragen stellen, aber am Ende nur 10 davon verwenden. Da Generatorausdrücke träge sind, werden nicht alle Berechnungen oder API-Aufrufe durchgeführt, wenn sie nicht angefordert werden. In diesem Fall ist die Verwendung von Generatorausdrücken effizienter.
Bei Listenauflösungen wird die gesamte Sammlung in den Speicher geladen. Aber Generatorausdrücke geben Ihnen einen Wert zurück, sobald Sie die next()
Aufrufs ist es damit fertig und braucht ihn nicht mehr im Speicher zu halten. Es wird nur ein einziges Element in den Speicher geladen. Wenn Sie über eine große Datei auf der Festplatte iterieren, kann es zu Speicherproblemen kommen, wenn die Datei zu groß ist. In diesem Fall ist die Verwendung eines Generatorausdrucks effizienter.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.