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

Python Enhancement Proposals

PEP 288 – Generator-Attribute und Ausnahmen

Autor:
Raymond Hettinger <python at rcn.com>
Status:
Zurückgezogen
Typ:
Standards Track
Erstellt:
21.03.2002
Python-Version:
2.5
Post-History:


Inhaltsverzeichnis

Zusammenfassung

Dieses PEP schlägt vor, Generatoren zu erweitern, indem Mechanismen zum Auslösen von Ausnahmen und zum Teilen von Daten mit laufenden Generatoren bereitgestellt werden.

Status

Dieses PEP ist zurückgezogen. Der Mechanismus zum Auslösen von Ausnahmen wurde erweitert und in PEP 343 übernommen. Die Fähigkeit zur Übergabe von Attributen fand nie Anklang, hatte keine klare Implementierung und keine saubere Möglichkeit für den laufenden Generator, auf seinen eigenen Namensraum zuzugreifen.

Begründung

Derzeit können nur klassenbasierte Iteratoren Attribute und Ausnahmebehandlung bereitstellen. Klassenbasierte Iteratoren sind jedoch schwieriger zu schreiben, weniger kompakt, weniger lesbar und langsamer. Eine bessere Lösung besteht darin, diese Fähigkeiten für Generatoren zu ermöglichen.

Die Aktivierung von Attributzuweisungen ermöglicht die Übergabe von Daten an und von laufenden Generatoren. Der Ansatz des Datenaustauschs über Attribute durchdringt Python. Andere Ansätze existieren, sind aber im Vergleich eher hackisch.

Ein weiterer evolutionärer Schritt ist die Hinzufügung einer Generator-Methode, um Ausnahmen an einen Generator übergeben zu können. Derzeit gibt es keine saubere Methode, um Ausnahmen von außerhalb des Generators auszulösen. Außerdem hilft die Übergabe von Generator-Ausnahmen, das try/finally-Verbot für Generatoren zu mildern. Der Bedarf ist besonders akut für Generatoren, die Puffer leeren oder Ressourcen bei Beendigung schließen müssen.

Die beiden Vorschläge sind abwärtskompatibel und erfordern keine neuen Schlüsselwörter. Sie werden für die Python-Version 2.5 empfohlen.

Spezifikation für Generator-Attribute

Im Wesentlichen besteht der Vorschlag darin, die Attributschreibweise für Klassen zu emulieren. Der einzige Knackpunkt ist, dass Generatoren keine Möglichkeit haben, auf Instanzen ihrer selbst zu verweisen. Daher sieht der Vorschlag vor, eine Funktion zum Entdecken der Referenz bereitzustellen. Zum Beispiel

def mygen(filename):
    self = sys.get_generator()
    myfile = open(filename)
    for line in myfile:
        if len(line) < 10:
            continue
        self.pos = myfile.tell()
        yield line.upper()

g = mygen('sample.txt')
line1 = g.next()
print 'Position', g.pos

Verwendungszwecke für Generator-Attribute umfassen

  1. Bereitstellung zusätzlicher Informationen für Generator-Clients (wie oben gezeigt).
  2. Externes Setzen von Kontrollflaggen, die den Generatorbetrieb steuern (möglicherweise telling a generator when to step in or step over data groups).
  3. Schreiben von Lazy-Consumern mit komplexen Ausführungszuständen (z. B. ein arithmetischer Encoder-Ausgabestrom).
  4. Schreiben von Co-Routinen (wie in Dr. Mertz' Artikeln demonstriert [1]).

Der Kontrollfluss von „yield“ und „next“ bleibt von diesem Vorschlag unverändert. Die einzige Änderung besteht darin, dass Daten zum und vom Generator übergeben werden können. Der Großteil der zugrunde liegenden Maschinerie ist bereits vorhanden, es muss nur noch die Zugriffsfunktion hinzugefügt werden.

Spezifikation für die Übergabe von Ausnahmen an Generatoren

Fügen Sie der Generator-Schnittstelle eine .throw(exception) Methode hinzu

def logger():
    start = time.time()
    log = []
    try:
        while True:
            log.append(time.time() - start)
            yield log[-1]
    except WriteLog:
        writelog(log)

g = logger()
for i in [10,20,40,80,160]:
    testsuite(i)
    g.next()
g.throw(WriteLog)

Es gibt keine bestehende Problemumgehung, um eine Ausnahme innerhalb eines Generators auszulösen. Es ist der einzige Fall in Python, bei dem aktiver Code nicht erwartet oder durchlaufen werden kann.

Die Übergabe von Generator-Ausnahmen hilft auch, eine inhärente Einschränkung von Generatoren zu adressieren, das Verbot der Verwendung von try/finally zum Auslösen von BereinigungsCode (PEP 255).

Hinweis A: Der Name der throw-Methode wurde aus mehreren Gründen gewählt. Raise ist ein Schlüsselwort und kann daher nicht als Methodennamen verwendet werden. Im Gegensatz zu raise, das sofort eine Ausnahme vom aktuellen Ausführungspunkt auslöst, gibt throw zuerst an den Generator zurück und löst dann die Ausnahme aus. Das Wort throw suggeriert das Einbringen der Ausnahme an einem anderen Ort. Das Wort throw ist bereits mit Ausnahmen in anderen Sprachen verbunden.

Es wurden alternative Methodennamen in Betracht gezogen: resolve(), signal(), genraise(), raiseinto() und flush(). Keiner davon passt so gut wie throw().

Hinweis B: Um die Syntax von throw() einfach zu halten, würde nur die Instanzversion der raise-Syntax unterstützt (keine Varianten für „raise string“ oder „raise class, instance“).

Der Aufruf von g.throw(instance) würde dem Schreiben von raise instance unmittelbar nach dem letzten yield entsprechen.

Referenzen


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

Zuletzt geändert: 2025-02-01 08:55:40 GMT