PEP 3142 – Hinzufügen einer „while“-Klausel zu Generator-Ausdrücken
- Autor:
- Gerald Britton <gerald.britton at gmail.com>
- Status:
- Abgelehnt
- Typ:
- Standards Track
- Erstellt:
- 12. Januar 2009
- Python-Version:
- 3.0
- Post-History:
- Resolution:
- Python-Dev Nachricht
Inhaltsverzeichnis
Zusammenfassung
Dieses PEP schlägt eine Erweiterung für Generator-Ausdrücke vor, indem eine „while“-Klausel hinzugefügt wird, die die bestehende „if“-Klausel ergänzt.
Begründung
Ein Generator-Ausdruck (PEP 289) ist eine prägnante Methode, um dynamisch generierte Objekte für Listen-Abfragen (PEP 202) bereitzustellen. Aktuelle Generator-Ausdrücke erlauben eine „if“-Klausel, um die zurückgegebenen Objekte zu filtern, die bestimmte Kriterien erfüllen. Da die „if“-Klausel jedoch für jedes Objekt ausgewertet wird, das potenziell zurückgegeben werden kann, ist es in einigen Fällen möglich, dass alle Objekte ab einem bestimmten Punkt abgewiesen werden. Zum Beispiel
g = (n for n in range(100) if n*n < 50)
was der Verwendung einer Generator-Funktion (PEP 255) entspricht
def __gen(exp):
for n in exp:
if n*n < 50:
yield n
g = __gen(iter(range(10)))
würde 0, 1, 2, 3, 4, 5, 6 und 7 ergeben, aber auch die Zahlen von 8 bis 99 berücksichtigen und alle abweisen, da n*n >= 50 für Zahlen in diesem Bereich gilt. Die Zulassung einer „while“-Klausel würde es ermöglichen, redundante Tests vorzeitig abzubrechen
g = (n for n in range(100) while n*n < 50)
würde ebenfalls 0, 1, 2, 3, 4, 5, 6 und 7 ergeben, aber bei 8 stoppen, da die Bedingung (n*n < 50) nicht mehr wahr ist. Dies wäre äquivalent zur Generator-Funktion
def __gen(exp):
for n in exp:
if n*n < 50:
yield n
else:
break
g = __gen(iter(range(100)))
Derzeit wäre, um dasselbe Ergebnis zu erzielen, entweder eine Generator-Funktion wie die obige zu schreiben oder die `takewhile`-Funktion aus `itertools` zu verwenden
from itertools import takewhile
g = takewhile(lambda n: n*n < 50, range(100))
Der `takewhile`-Code erzielt das gleiche Ergebnis wie die vorgeschlagene Syntax, wenn auch auf eine längere (manche würden sagen „weniger elegante“) Weise. Außerdem erfordert die `takewhile`-Version einen zusätzlichen Funktionsaufruf (das Lambda im obigen Beispiel) mit der entsprechenden Leistungsstrafe. Ein einfacher Test zeigt, dass
for n in (n for n in range(100) if 1): pass
etwa 10 % besser abschneidet als
for n in takewhile(lambda n: 1, range(100)): pass
obwohl sie ähnliche Ergebnisse erzielen. (Das erste Beispiel verwendet einen Generator; `takewhile` ist ein Iterator). Bei ähnlicher Implementierung sollte eine „while“-Klausel ungefähr die gleiche Leistung wie die heutige „if“-Klausel erbringen.
Der Leser mag sich fragen, ob die „if“- und „while“-Klauseln sich gegenseitig ausschließen sollten. Es gibt gute Beispiele, die zeigen, dass es Zeiten gibt, in denen beide mit gutem Vorteil eingesetzt werden können. Zum Beispiel
p = (p for p in primes() if p > 100 while p < 1000)
sollte Primzahlen zwischen 100 und 1000 zurückgeben, vorausgesetzt, ich habe einen Generator primes(), der Primzahlen liefert.
Das Hinzufügen einer „while“-Klausel zu Generator-Ausdrücken behält die kompakte Form bei und fügt gleichzeitig eine nützliche Einrichtung zum vorzeitigen Abbruch des Ausdrucks hinzu.
Danksagungen
Raymond Hettinger schlug das Konzept der Generator-Ausdrücke erstmals im Januar 2002 vor.
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-3142.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT