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

Python Enhancement Proposals

PEP 3117 – Postfix-Typdeklarationen

Autor:
Georg Brandl <georg at python.org>
Status:
Abgelehnt
Typ:
Standards Track
Erstellt:
01-Apr-2007
Python-Version:
3.0
Post-History:


Inhaltsverzeichnis

Zusammenfassung

Diese PEP schlägt die Hinzufügung einer Postfix-Syntax für Typdeklarationen zu Python vor. Sie spezifiziert auch eine neue typedef-Anweisung, die zum Erstellen neuer Zuordnungen zwischen Typen und Deklaratoren verwendet wird.

Ihre Annahme wird das Benutzererlebnis von Python erheblich verbessern und eine der Macken beseitigen, die Benutzer anderer Programmiersprachen davon abhalten, zu Python zu wechseln.

Begründung

Python leidet seit langem unter dem Mangel an expliziten Typdeklarationen. Als einer der wenigen Aspekte, in denen sich die Sprache von ihrem Zen unterscheidet, hat diese Macke viele Diskussionen zwischen Python-Häretikern und Mitgliedern der PSU (einige Beispiele siehe [EX1], [EX2] oder [EX3]) ausgelöst und auch einen groß angelegten Unternehmenserfolg unwahrscheinlich gemacht.

Wenn man jedoch diesem Elend ein Ende setzen will, muss eine anständige Python-Syntax gefunden werden. In fast allen Sprachen, die sie haben, fehlt es Typdeklarationen an dieser Qualität: Sie sind umständlich, erfordern oft *mehrere Wörter* für einen einzigen Typ, oder sie sind schwer zu verstehen (z.B. verwendet eine bestimmte Sprache völlig unrelated [1] Adjektive wie dim für die Typdeklaration).

Daher kombiniert diese PEP den Schritt zu Typdeklarationen mit einem weiteren kühnen Schritt, der erneut beweist, dass Python nicht nur zukunftssicher, sondern auch zukunftsfreundlich ist: die Einführung von Unicode-Zeichen als integralen Bestandteil des Quellcodes.

Unicode ermöglicht es, mit viel weniger Zeichen viel mehr auszudrücken, was mit dem Zen („Lesbarkeit zählt.“) übereinstimmt. Außerdem entfällt die Notwendigkeit einer separaten Typdeklarationsanweisung, und nicht zuletzt zieht Python damit mit Perl 6 gleich, das bereits Unicode für seine Operatoren verwendet. [2]

Spezifikation

Wenn der Typdeklarationsmodus in Betrieb ist, wird die Grammatik so geändert, dass jedes NAME aus zwei Teilen bestehen muss: einem Namen und einem Typdeklarator, der genau ein Unicode-Zeichen ist.

Der Deklarator gibt eindeutig den Typ des Namens an, und wenn er auf der linken Seite eines Ausdrucks vorkommt, wird dieser Typ erzwungen: Eine InquisitionError-Ausnahme wird ausgelöst, wenn der zurückgegebene Typ nicht mit dem deklarierten Typ übereinstimmt. [3]

Auch die Ergebnistypen von Funktionsaufrufen müssen angegeben werden. Wenn das Ergebnis des Aufrufs nicht den deklarierten Typ hat, wird eine InquisitionError ausgelöst. Vorsicht: Der Deklarator für das Ergebnis sollte nicht mit dem Deklarator für das Funktionsobjekt verwechselt werden (siehe Beispiel unten).

Typdeklaratoren nach Namen, die nur gelesen und nicht zugewiesen werden, sind nicht unbedingt erforderlich, werden aber trotzdem erzwungen (siehe Python Zen: „Explizit ist besser als implizit.“).

Die Zuordnung zwischen Typen und Deklaratoren ist nicht statisch. Sie kann vom Programmierer vollständig angepasst werden, aber zur Bequemlichkeit gibt es einige vordefinierte Zuordnungen für einige integrierte Typen

Typ Deklarator
object � (ERSETZUNGSZEICHEN)
int ℕ (DOPPELT GESTRICHENE GROSSBUCHSTABE N)
float ℮ (GESCHÄTZTES SYMBOL)
bool ✓ (HÄKCHEN)
complex ℂ (DOPPELT GESTRICHENE GROSSBUCHSTABE C)
str ✎ (LOWER RIGHT PENCIL)
unicode ✒ (BLACK NIB)
tuple ⒯ (Klammeraffe LATIN KLEINBUCHSTABE T)
list ♨ (HEISSE QUELLEN)
dict ⧟ (DOPPELSEITIGER MULTIMAP)
set ∅ (LEERE MENGE) (Hinweis: dies gilt auch für vollständige Mengen)
frozenset ☃ (SCHNEEMANN)
datetime ⌚ (UHR)
function ƛ (LATEINISCHER KLEINBUCHSTABE LAMBDA MIT SCHRÄGSTRICH)
generator ⚛ (ATOM-SYMBOL)
Exception ⌁ (ELEKTRISCHER PFEIL)

Der Deklarator für den None-Typ ist ein Nullbreitenleerzeichen.

Diese Zeichen sollten für jeden Programmierer offensichtlich, leicht zu merken und einzugeben sein.

Unicode-Ersatzeinheiten

Da selbst in unserer modernen, globalisierten Welt noch einige altmodische Rebellen gibt, die Unicode nicht in ihrem Quellcode verwenden können oder wollen, und da Python eine nachsichtige Sprache ist, wird für diese eine Fallback-Lösung bereitgestellt

Anstelle des einzelnen Unicode-Zeichens können sie name${UNICODE NAME DES DEKLARATORS}$ eingeben. Zum Beispiel sind diese beiden Funktionsdefinitionen äquivalent

def fooƛ(xℂ):
    return None

und

def foo${LATIN SMALL LETTER LAMBDA WITH STROKE}$(x${DOUBLE-STRUCK CAPITAL C}$):
    return None${ZERO WIDTH NO-BREAK SPACE}$

Das ist immer noch gut lesbar und macht die volle Leistung des Typ-annotierten Pythons für ASCII-Gläubige verfügbar.

Die typedef-Anweisung

Die Zuordnung zwischen Typen und Deklaratoren kann mit dieser neuen Anweisung erweitert werden.

Die Syntax lautet wie folgt

typedef_stmt  ::=  "typedef" expr DECLARATOR

wobei expr zu einem Typobjekt aufgelöst wird. Zur Bequemlichkeit kann die typedef-Anweisung auch mit der class-Anweisung für neue Klassen gemischt werden, wie hier

typedef class Foo☺(object�):
    pass

Beispiel

Dies ist die Standardfunktion os.path.normpath, konvertiert in Typdeklarationssyntax

def normpathƛ(path✎)✎:
    """Normalize path, eliminating double slashes, etc."""
    if path✎ == '':
        return '.'
    initial_slashes✓ = path✎.startswithƛ('/')✓
    # POSIX allows one or two initial slashes, but treats three or more
    # as single slash.
    if (initial_slashes✓ and
        path✎.startswithƛ('//')✓ and not path✎.startswithƛ('///')✓)✓:
        initial_slashesℕ = 2
    comps♨ = path✎.splitƛ('/')♨
    new_comps♨ = []♨
    for comp✎ in comps♨:
        if comp✎ in ('', '.')⒯:
            continue
        if (comp✎ != '..' or (not initial_slashesℕ and not new_comps♨)✓ or
             (new_comps♨ and new_comps♨[-1]✎ == '..')✓)✓:
            new_comps♨.appendƛ(comp✎)
        elif new_comps♨:
            new_comps♨.popƛ()✎
    comps♨ = new_comps♨
    path✎ = '/'.join(comps♨)✎
    if initial_slashesℕ:
        path✎ = '/'*initial_slashesℕ + path✎
    return path✎ or '.'

Wie Sie deutlich sehen können, verleihen die Typdeklarationen Ausdrucksstärke und lassen den Code gleichzeitig viel professioneller aussehen.

Kompatibilitätsprobleme

Um den Typdeklarationsmodus zu aktivieren, muss man schreiben

from __future__ import type_declarations

was die Unicode-Analyse der Quelle aktiviert [4], macht typedef zu einem Schlüsselwort und erzwingt korrekte Typen für alle Zuweisungen und Funktionsaufrufe.

Ablehnung

Nach sorgfältiger Überlegung, viel Selbstreflexion, Zähneknirschen und Zerreißen von Gewändern wurde beschlossen, diese PEP abzulehnen.

Referenzen

Danksagungen

Vielen Dank an Armin Ronacher, Alexander Schremmer und Marek Kubica, die geholfen haben, die am besten geeigneten und einprägsamsten Deklaratoren für integrierte Typen zu finden.

Vielen Dank auch an das Unicode-Konsortium für die Aufnahme all dieser nützlichen Zeichen in den Unicode-Standard.


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

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