Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

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.


Quelle: https://github.com/python/peps/blob/main/peps/pep-3142.rst

Zuletzt geändert: 2025-02-01 08:59:27 GMT