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

Python Enhancement Proposals

PEP 727 – Dokumentation in annotierten Metadaten

Autor:
Sebastián Ramírez <tiangolo at gmail.com>
Sponsor:
Jelle Zijlstra <jelle.zijlstra at gmail.com>
Discussions-To:
Discourse thread
Status:
Zurückgezogen
Typ:
Standards Track
Thema:
Typisierung
Erstellt:
28-Aug-2023
Python-Version:
3.13
Post-History:
30-Aug-2023

Inhaltsverzeichnis

Zusammenfassung

Dieses PEP schlägt einen standardisierten Weg vor, um Dokumentationsstrings für Python-Symbole bereitzustellen, die mit Annotated definiert sind, unter Verwendung einer neuen Klasse typing.Doc.

Rücknahme eines PEP

Die Resonanz auf dieses PEP war überwiegend negativ, wobei Bedenken hinsichtlich Ausführlichkeit und Lesbarkeit geäußert wurden. Infolgedessen wurde dieses PEP zurückgezogen.

Motivation

Es gibt bereits einen klar definierten Weg, um Dokumentationen für Klassen, Funktionen, Klassenmethoden und Module bereitzustellen: die Verwendung von Docstrings.

Derzeit gibt es keinen formalisierten Standard zur Bereitstellung von Dokumentationsstrings für andere Symboltypen: Parameter, Rückgabewerte, klassenbezogene Variablen (Klassenvariablen und Instanzvariablen), lokale Variablen und Typ-Aliasse.

Nichtsdestotrotz wurden zur Dokumentation der meisten dieser zusätzlichen Symbole mehrere Konventionen als Mikrosyntaxen innerhalb von Docstrings geschaffen und sind derzeit gängige Praxis: Sphinx, numpydoc, Google, Keras usw.

Es gibt zwei Szenarien, in denen diese Konventionen von Tools unterstützt würden: für Autoren beim **Bearbeiten** des Inhalts der Dokumentationsstrings und für Benutzer beim **Rendern** dieses Inhalts in irgendeiner Weise (auf Dokumentationsseiten, Tooltips in Editoren usw.).

Da jede dieser Konventionen eine Mikrosyntax innerhalb eines Strings verwendet, können Editoren beim **Bearbeiten** dieser Docstrings nicht einfach Unterstützung für Autovervollständigung, Inline-Fehler für fehlerhafte Syntax usw. bereitstellen. Jede Art von **Bearbeitungs**unterstützung für diese Konventionen würde zusätzlich zur Unterstützung für die Bearbeitung von Standard-Python-Syntax erfolgen.

Bei der Dokumentation von Parametern nach aktuellen Konventionen, da sich der Docstring an einer anderen Stelle im Code befindet als die eigentlichen Parameter und eine Duplizierung von Informationen (der Parametername) erfordert, befinden sich die Informationen zu einem Parameter leicht an einer Stelle im Code, die weit von der Deklaration des eigentlichen Parameters entfernt ist, und sind davon getrennt. Das bedeutet, es ist leicht, eine Funktion umzustrukturieren, einen Parameter zu entfernen und zu vergessen, seine Dokumentation zu entfernen. Dasselbe geschieht, wenn ein neuer Parameter hinzugefügt wird: Es ist leicht zu vergessen, die Docstring dafür hinzuzufügen.

Und aufgrund dieser gleichen Informationsduplizierung (des Parameter namens) benötigen Editoren und andere Tools komplexe benutzerdefinierte Logik, um die Konsistenz der Parameter in der Signatur und in ihrem Docstring zu überprüfen oder sicherzustellen, oder sie unterstützen dies einfach nicht vollständig.

Da diese bestehenden Konventionen unterschiedliche Arten von Mikrosyntaxen innerhalb von Strings sind, erfordert das robuste Parsen für das **Rendern** komplexe Logik, die von den unterstützenden Tools implementiert werden muss. Darüber hinaus haben Bibliotheken und Tools keine einfache Möglichkeit, die Dokumentation für jeden einzelnen Parameter oder jede Variable zur Laufzeit zu erhalten, ohne von einem spezifischen Docstring-Konventions-Parser abhängig zu sein. Der Zugriff auf die Dokumentationsstrings von Parametern zur Laufzeit wäre beispielsweise nützlich, um den Inhalt der Dokumentation jedes Parameters zu testen, die Konsistenz über mehrere ähnliche Funktionen hinweg zu gewährleisten oder um dieselbe Parameterdokumentation auf andere Weise zu extrahieren und bereitzustellen (z. B. eine API mit FastAPI, eine CLI mit Typer usw.).

Einige dieser früheren Formate versuchten, den Mangel an Typ-Annotationen in älteren Python-Versionen zu berücksichtigen, indem sie Typinformationen in die Docstrings aufnahmen (z. B. Sphinx, numpydoc), aber diese Informationen müssen nun nicht mehr in Docstrings enthalten sein, da es nun eine offizielle Syntax für Typ-Annotationen gibt.

Begründung

Dieser Vorschlag zielt darauf ab, diese Mängel zu beheben, indem die Informationen in Docstrings erweitert und ergänzt werden, die Abwärtskompatibilität mit bestehenden Docstrings beibehalten wird (sie werden nicht veraltet erklärt) und dies auf eine Weise geschieht, die die Python-Sprache und -Struktur nutzt, über Typ-Annotationen mit Annotated und einer neuen Klasse Doc in typing.

Der Grund, warum dies in der Standardbibliothek von Python und nicht in einem externen Paket liegen würde, ist, dass obwohl die Implementierung sehr trivial wäre, die tatsächliche Stärke und der Nutzen daraus als Standard kämen, um die Nutzung durch Bibliotheksautoren zu erleichtern und eine Standardmethode zur Dokumentation von Python-Symbolen unter Verwendung von Annotated bereitzustellen. Einige Tool-Anbieter (zumindest VS Code und PyCharm) haben gezeigt, dass sie die Implementierung von Unterstützung für dieses PEP nur dann in Erwägung ziehen würden, wenn es sich um einen Standard handelt.

Dies erklärt die aktuelle Verwendung von Docstrings nicht für veraltet; Docstrings sollten als bevorzugte Dokumentationsmethode betrachtet werden, wenn verfügbar (nicht verfügbar für Typ-Aliasse, Parameter usw.). Und Docstrings würden durch diesen Vorschlag für die spezifische Dokumentation der Symbole ergänzt, die mit Annotated deklariert werden können (derzeit nur durch die verschiedenen verfügbaren Mikrosyntax-Konventionen abgedeckt).

Dies sollte für normale Entwickler (Bibliotheksbenutzer) relativ transparent sein, es sei denn, sie öffnen manuell die Quelldateien von Bibliotheken, die es annehmen.

Es sollte für Bibliotheksautoren, die es annehmen möchten, optional sein, und sie sollten frei entscheiden können, ob sie es verwenden oder nicht.

Es wäre nur für Bibliotheken nützlich, die bereit sind, optionale Typ-Hints zu verwenden.

Zusammenfassung

Hier ist eine kurze Zusammenfassung der Merkmale dieses Vorschlags im Vergleich zu aktuellen Konventionen

  • Das **Bearbeiten** wäre standardmäßig vollständig unterstützt von jedem Editor (aktuell oder zukünftig), der Python-Syntax unterstützt, einschließlich Syntaxfehlern, Syntaxhervorhebung usw.
  • Das **Rendern** wäre für statische Tools (Tools, die keine Laufzeitausführung benötigen) relativ einfach zu implementieren, da die Informationen aus der AST extrahiert werden können, die sie normalerweise bereits erstellen.
  • Deduplizierung von Informationen: Der Name eines Parameters wird an einer einzigen Stelle definiert, nicht in einem Docstring dupliziert.
  • Beseitigung der Möglichkeit von Inkonsistenzen beim Entfernen eines Parameters oder einer Klassenvariablen und Vergessen, dessen Dokumentation zu entfernen.
  • Minimierung der Wahrscheinlichkeit, dass ein neuer Parameter oder eine neue Klassenvariable hinzugefügt und vergessen wird, dessen Dokumentation hinzuzufügen.
  • Beseitigung der Möglichkeit von Inkonsistenzen zwischen dem Namen eines Parameters in der Signatur und dem Namen im Docstring bei Umbenennung.
  • Zugriff auf den Dokumentationsstring für jedes Symbol zur Laufzeit, auch in bestehenden (älteren) Python-Versionen.
  • Eine formalisierte Methode zur Dokumentation anderer Symbole, wie Typ-Aliasse, die Annotated verwenden könnten.
  • Keine zu erlernende Mikrosyntax für Neulinge, es ist nur Python-Syntax.
  • ParametereDokumentationsvererbung für Funktionen, die von ParamSpec erfasst werden.

Spezifikation

Der Hauptvorschlag ist die Einführung einer neuen Klasse, typing.Doc. Diese Klasse sollte nur innerhalb von Annotated-Annotationen verwendet werden. Sie nimmt ein einzelnes positionsbasiertes String-Argument entgegen. Sie sollte verwendet werden, um die beabsichtigte Bedeutung und Verwendung des mit Annotated deklarierten Symbols zu dokumentieren.

Zum Beispiel:

from typing import Annotated, Doc

class User:
    name: Annotated[str, Doc("The user's name")]
    age: Annotated[int, Doc("The user's age")]

    ...

Wenn Annotated als Typ-Annotation verwendet wird, dokumentiert jede typing.Doc darin das annotierte Symbol.

Wenn Annotated zur Deklaration eines Typ-Aliases verwendet wird, dokumentiert typing.Doc dann das Typ-Alias-Symbol.

Zum Beispiel:

from typing import Annotated, Doc, TypeAlias

from external_library import UserResolver

CurrentUser: TypeAlias = Annotated[str, Doc("The current system user"), UserResolver()]

def create_user(name: Annotated[str, Doc("The user's name")]): ...

def delete_user(name: Annotated[str, Doc("The user to delete")]): ...

In diesem Fall, wenn ein Benutzer CurrentUser importiert, könnten Tools wie Editoren einen Tooltip mit dem Dokumentationsstring anzeigen, wenn ein Benutzer über dieses Symbol fährt, oder Dokumentationstools könnten den Typ-Alias mit seiner Dokumentation in ihrer generierten Ausgabe einschließen.

Für Tools, die die Informationen zur Laufzeit extrahieren, würden sie normalerweise get_type_hints() mit dem Parameter include_extras=True verwenden, und da Annotated normalisiert ist (auch mit Typ-Aliassen), bedeutet dies, dass sie die letzte verfügbare typing.Doc verwenden sollten, falls mehr als eine verwendet wird, da dies die letzte ist, die verwendet wurde.

Zur Laufzeit haben typing.Doc-Instanzen ein Attribut documentation mit dem an sie übergebenen String.

Wenn die Signatur einer Funktion von einem ParamSpec erfasst wird, sollten alle mit den Parametern verbundenen Dokumentationsstrings beibehalten werden.

Jedes Tool, das typing.Doc-Objekte verarbeitet, sollte den String als Docstring interpretieren und daher Leerzeichen so normalisieren, als ob inspect.cleandoc() verwendet worden wäre.

Der an typing.Doc übergebene String sollte die Form eines gültigen Docstrings haben. Dies bedeutet, dass f-Strings und String-Operationen nicht verwendet werden sollten. Da dies von der Python-Laufzeit nicht erzwungen werden kann, sollten sich Tools nicht auf dieses Verhalten verlassen.

Wenn Tools, die **Rendern** anbieten, die rohe Signatur anzeigen, könnten sie konfigurierbar machen, ob der gesamte rohe Annotated-Code angezeigt werden soll, aber standardmäßig sollten sie Annotated und dessen interne Metadaten nicht einschließen, sondern nur den Typ der annotierten Symbole. Wenn diese Tools typing.Doc und das Rendern auf andere Weise als nur eine rohe Signatur unterstützen, sollten sie den an typing.Doc übergebenen String auf eine praktische Weise anzeigen, die die Beziehung zwischen dem dokumentierten Symbol und dem Dokumentationsstring zeigt.

Tools, die **Rendern** anbieten, könnten Möglichkeiten anbieten, zu konfigurieren, wo die Parameterdokumentation und der Prosa-Docstring auf verschiedene Weise angezeigt werden sollen. Andernfalls könnten sie einfach zuerst den Prosa-Docstring und dann die Parameterdokumentation anzeigen.

Beispiele

Klassenattribute können dokumentiert werden

from typing import Annotated, Doc

class User:
    name: Annotated[str, Doc("The user's name")]
    age: Annotated[int, Doc("The user's age")]

    ...

Ebenso wie Funktions- oder Methodenparameter und Rückgabewerte

from typing import Annotated, Doc

def create_user(
    name: Annotated[str, Doc("The user's name")],
    age: Annotated[int, Doc("The user's age")],
    cursor: DatabaseConnection | None = None,
) -> Annotated[User, Doc("The created user after saving in the database")]:
    """Create a new user in the system.

    It needs the database connection to be already initialized.
    """
    pass

Abwärtskompatibilität

Dieser Vorschlag ist vollständig abwärtskompatibel mit bestehendem Code und erklärt die bestehende Nutzung von Docstring-Konventionen nicht für veraltet.

Für Entwickler, die ihn annehmen möchten, bevor er in der Standardbibliothek verfügbar ist, oder um ältere Python-Versionen zu unterstützen, können sie typing_extensions verwenden und Doc von dort importieren und verwenden.

Zum Beispiel:

from typing import Annotated
from typing_extensions import Doc

class User:
    name: Annotated[str, Doc("The user's name")]
    age: Annotated[int, Doc("The user's age")]

    ...

Sicherheitsimplikationen

Es sind keine bekannten Sicherheitsprobleme bekannt.

Wie man das lehrt

Der Hauptmechanismus der Dokumentation sollte weiterhin standardmäßige Docstrings für Prosa-Informationen sein. Dies gilt für Module, Klassen, Funktionen und Methoden.

Für Autoren, die diesen Vorschlag annehmen möchten, um mehr Granularität hinzuzufügen, können sie typing.Doc innerhalb von Annotated-Annotationen für die Symbole verwenden, die es unterstützen.

Bibliotheksautoren, die diesen Vorschlag annehmen möchten und dabei die Abwärtskompatibilität mit älteren Python-Versionen beibehalten wollen, sollten typing_extensions.Doc anstelle von typing.Doc verwenden.

Referenzimplementierung

typing.Doc ist äquivalent implementiert zu

class Doc:
    def __init__(self, documentation: str, /):
        self.documentation = documentation

Es wurde im Paket typing_extensions implementiert.

Übersicht über andere Sprachen

Hier ist eine kurze Übersicht darüber, wie andere Sprachen ihre Symbole dokumentieren.

Java

Java-Funktionen und ihre Parameter werden mit Javadoc dokumentiert, einem speziellen Kommentarformat, das über der Funktionsdefinition platziert wird. Dies wäre ähnlich wie bei aktuellen Python-Docstring-Mikrosyntax-Konventionen (aber nur eine).

Zum Beispiel:

/**
* Returns an Image object that can then be painted on the screen.
* The url argument must specify an absolute <a href="#{@link}">{@link URL}</a>. The name
* argument is a specifier that is relative to the url argument.
* <p>
* This method always returns immediately, whether or not the
* image exists. When this applet attempts to draw the image on
* the screen, the data will be loaded. The graphics primitives
* that draw the image will incrementally paint on the screen.
*
* @param  url  an absolute URL giving the base location of the image
* @param  name the location of the image, relative to the url argument
* @return      the image at the specified URL
* @see         Image
*/
public Image getImage(URL url, String name) {
  try {
    return getImage(new URL(url, name));
  } catch (MalformedURLException e) {
    return null;
  }
}

JavaScript

Sowohl JavaScript als auch TypeScript verwenden ein ähnliches System wie Javadoc.

JavaScript verwendet JSDoc.

Zum Beispiel:

/**
* Represents a book.
* @constructor
* @param {string} title - The title of the book.
* @param {string} author - The author of the book.
*/
function Book(title, author) {
}

TypeScript

TypeScript hat seine eigene JSDoc-Referenz mit einigen Variationen.

Zum Beispiel:

// Parameters may be declared in a variety of syntactic forms
/**
* @param {string}  p1 - A string param.
* @param {string=} p2 - An optional param (Google Closure syntax)
* @param {string} [p3] - Another optional param (JSDoc syntax).
* @param {string} [p4="test"] - An optional param with a default value
* @returns {string} This is the result
*/
function stringsStringStrings(p1, p2, p3, p4) {
    // TODO
}

Rust

Rust verwendet eine weitere ähnliche Variante einer Mikrosyntax in Doc Comments.

Aber es hat keine besonders gut definierte Mikrosyntaxstruktur, um anzugeben, welche Dokumentation sich auf welches Symbol/Parameter bezieht, außer dem, was aus reinem Markdown abgeleitet werden kann.

Zum Beispiel:

#![crate_name = "doc"]

/// A human being is represented here
pub struct Person {
   /// A person must have a name, no matter how much Juliet may hate it
   name: String,
}

impl Person {
   /// Returns a person with the name given them
   ///
   /// # Arguments
   ///
   /// * `name` - A string slice that holds the name of the person
   ///
   /// # Examples
   ///
   /// ```
   /// // You can have rust code between fences inside the comments
   /// // If you pass --test to `rustdoc`, it will even test it for you!
   /// use doc::Person;
   /// let person = Person::new("name");
   /// ```
   pub fn new(name: &str) -> Person {
      Person {
            name: name.to_string(),
      }
   }

   /// Gives a friendly hello!
   ///
   /// Says "Hello, [name](Person::name)" to the `Person` it is called on.
   pub fn hello(& self) {
      println!("Hello, {}!", self.name);
   }
}

fn main() {
   let john = Person::new("John");

   john.hello();
}

Go Lang

Go verwendet ebenfalls eine Form von Doc Comments.

Es gibt keine gut definierte Mikrosyntaxstruktur, um anzugeben, welche Dokumentation sich auf welches Symbol/Parameter bezieht, aber Parameter können ohne spezielle Syntax oder Markierung namentlich referenziert werden. Dies bedeutet auch, dass gewöhnliche Wörter, die im Dokumentationstext vorkommen könnten, als Parameternamen vermieden werden sollten.

package strconv

// Quote returns a double-quoted Go string literal representing s.
// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
// for control characters and non-printable characters as defined by IsPrint.
func Quote(s string) string {
   ...
}

Abgelehnte Ideen

Standardisierung aktueller Docstrings

Eine mögliche Alternative wäre es, eines der bestehenden Docstring-Formate zu unterstützen und als Standard zu fördern. Aber das würde nur die Standardisierung lösen.

Es würde keines der anderen Probleme lösen, die sich aus der Verwendung einer Mikrosyntax innerhalb eines Docstrings anstelle von reinem Python-Syntax ergeben, wie oben im Abschnitt **Begründung – Zusammenfassung** beschrieben.

Zusätzliche Metadaten und Dekorator

Einige Ideen vor diesem Vorschlag beinhalteten eine Funktion doc() anstelle der einzelnen Klasse Doc mit mehreren Parametern, um anzugeben, ob ein Objekt zur Verwendung nicht empfohlen wird, welche Ausnahmen es auslösen kann usw. Um auch Funktionen und Klassen veralten lassen zu können, wurde auch erwartet, dass doc() als Dekorator verwendet werden könnte. Aber diese Funktionalität wird durch typing.deprecated() in PEP 702 abgedeckt, sodass sie aus diesem Vorschlag gestrichen wurde.

Eine Möglichkeit, zusätzliche Informationen zu deklarieren, könnte in Zukunft weiterhin nützlich sein, aber basierend auf frühem Feedback zu dieser Idee wurde alles auf zukünftige Vorschläge verschoben.

Dies verlagerte auch den Fokus von einer allumfassenden Funktion doc() mit mehreren Parametern auf eine einzelne Doc-Klasse, die in Annotated verwendet werden kann, in einer Weise, die mit anderen zukünftigen Vorschlägen kombiniert werden könnte.

Diese Designänderung ermöglicht auch eine bessere Interoperabilität mit anderen Vorschlägen wie typing.deprecated(), da zukünftig in Betracht gezogen werden könnte, typing.deprecated() ebenfalls in Annotated zu erlauben, um einzelne Parameter zu veraltet zu erklären, die mit Doc koexistieren.

String unter Definition

Eine alternative Möglichkeit, die in der Diskussion vorgeschlagen wurde, ist die Deklaration eines Strings unter der Definition eines Symbols und die Laufzeitbereitzustellung von Zugriff auf diese Werte.

class User:
    name: str
    "The user's name"
    age: int
    "The user's age"

    ...

Dies wurde bereits in PEP 224 vorgeschlagen und abgelehnt, hauptsächlich aufgrund der Mehrdeutigkeit, wie der String mit dem Symbol verbunden ist, das er dokumentiert.

Zusätzlich gäbe es keine Möglichkeit, in früheren Python-Versionen Laufzeitzugriff auf diesen Wert bereitzustellen.

Einfacher String in Annotated

In der Diskussion wurde auch vorgeschlagen, einen einfachen String innerhalb von Annotated zu verwenden.

from typing import Annotated

class User:
    name: Annotated[str, "The user's name"]
    age: Annotated[int, "The user's age"]

    ...

Aber dies würde eine vordefinierte Bedeutung für jeden einfachen String innerhalb von Annotated schaffen, und jedes Tool, das einfache Strings für andere Zwecke darin verwendete, was derzeit erlaubt ist, wäre nun ungültig.

Ein explizites typing.Doc macht es kompatibel mit aktuell gültigen Verwendungen von Annotated.

Ein weiterer Annotations-ähnlicher Typ

In der Diskussion wurde vorgeschlagen, einen neuen Typ ähnlich wie Annotated zu definieren. Er würde den Typ und einen Parameter mit dem Dokumentationsstring entgegennehmen.

from typing import Doc

class User:
    name: Doc[str, "The user's name"]
    age: Doc[int, "The user's age"]

    ...

Diese Idee wurde abgelehnt, da sie nur diesen Anwendungsfall unterstützen würde und die Kombination mit Annotated für andere Zwecke (z. B. mit FastAPI-Metadaten, Pydantic-Feldern usw.) oder das Hinzufügen zusätzlicher Metadaten neben dem Dokumentationsstring (z. B. Veralterung) erschweren würde.

Übertragung von Dokumentation aus Typ-Aliassen

Eine frühere Version dieses Vorschlags sah vor, dass, wenn Typ-Aliasse mit Annotated deklariert wurden und diese Typ-Aliasse in Annotationen verwendet wurden, der Dokumentationsstring auf das annotierte Symbol übertragen würde.

Zum Beispiel:

from typing import Annotated, Doc, TypeAlias


UserName: TypeAlias = Annotated[str, Doc("The user's name")]


def create_user(name: UserName): ...

def delete_user(name: UserName): ...

Dies wurde nach Rückmeldungen vom Maintainer einer der Hauptkomponenten zur Bereitstellung von Editor-Unterstützung abgelehnt.

Kurzschreibweise mit Slices

In der Diskussion wurde vorgeschlagen, eine Kurzschreibweise mit Slices zu verwenden.

is_approved: Annotated[str: "The status of a PEP."]

Obwohl dies eine sehr clevere Idee ist und die Notwendigkeit einer neuen Doc-Klasse beseitigen würde, erlaubt die Laufzeitausführung von aktuellen Python-Versionen dies nicht.

Zur Laufzeit benötigt Annotated mindestens zwei Argumente, und das erste Argument muss ein Typ sein; es stürzt ab, wenn es ein Slice ist.

Offene Fragen

Ausführlichkeit

Das Hauptargument dagegen wäre die erhöhte Ausführlichkeit.

Wenn die Signatur nicht unabhängig von der Dokumentation betrachtet würde und auch der Körper der Funktion mit dem Docstring gemessen würde, wäre die Gesamtausführlichkeit etwas ähnlich, da dieser Vorschlag einige Inhalte vom Docstring im Körper zur Signatur verlagert.

Betrachtet man nur die Signatur, ohne den Körper, könnten diese viel länger sein als derzeit, sie könnten mehr als eine Seite lang werden. Im Gegenzug wären die äquivalenten Docstrings, die derzeit mehr als eine Seite lang sind, viel kürzer.

Beim Vergleich der Gesamtausführlichkeit, einschließlich der Signatur und des Docstrings, wäre die Haupt zusätzliche Ausführlichkeit von der Verwendung von Annotated und typing.Doc zu erwarten. Wenn Annotated häufiger verwendet würde, könnte es sinnvoll sein, eine verbesserte kürzere Syntax dafür und für die Metadaten, die es tragen würde, zu haben. Aber das wäre nur sinnvoll, sobald Annotated weiter verbreitet ist.

Auf der anderen Seite würde diese Ausführlichkeit Endbenutzer nicht betreffen, da sie den internen Code, der typing.Doc verwendet, nicht sehen würden. Die Mehrheit der Benutzer würde mit Bibliotheken über Editoren interagieren, ohne die Interna zu betrachten, und wenn überhaupt, hätten sie Tooltips von Editoren, die diesen Vorschlag unterstützen.

Die Kosten für die Bewältigung der zusätzlichen Ausführlichkeit würden hauptsächlich von den Bibliotheksmaintainern getragen, die diese Funktion nutzen.

Dieses Argument könnte analog zum Argument gegen Typ-Annotationen im Allgemeinen sein, da diese tatsächlich die Ausführlichkeit erhöhen, im Austausch für ihre Funktionen. Aber auch hier, wie bei Typ-Annotationen, wäre dies optional und nur von denen zu nutzen, die bereit sind, die zusätzliche Ausführlichkeit im Austausch für die Vorteile in Kauf zu nehmen.

Natürlich möchten fortgeschrittene Benutzer möglicherweise den Quellcode der Bibliotheken einsehen, und wenn die Autoren dieser Bibliotheken dies annehmen würden, müssten diese fortgeschrittenen Benutzer diesen Code mit zusätzlicher Signatur-Ausführlichkeit anstelle von Docstring-Ausführlichkeit betrachten.

Autoren, die sich entscheiden, es nicht anzunehmen, sollten frei sein, weiterhin Docstrings mit einem beliebigen Format ihrer Wahl zu verwenden, keine Docstrings überhaupt usw.

Dennoch besteht eine hohe Wahrscheinlichkeit, dass Bibliotheksautoren unter Druck gesetzt werden könnten, dies zu übernehmen, wenn es die bevorzugte Lösung würde.

Dokumentation ist keine Typisierung

Es könnte auch argumentiert werden, dass Dokumentation nicht wirklich Teil der Typisierung ist oder dass sie in einem anderen Modul leben sollte. Oder dass diese Informationen nicht Teil der Signatur sein sollten, sondern an einem anderen Ort (wie dem Docstring) leben sollten.

Nichtsdestotrotz könnten Typ-Annotationen in Python bereits standardmäßig als zusätzliche Metadaten betrachtet werden: Sie tragen zusätzliche Informationen über Variablen, Parameter, Rückgabetypen und haben standardmäßig kein Laufzeitverhalten. Und dieser Vorschlag würde ihnen eine weitere Art von Metadaten hinzufügen.

Es könnte argumentiert werden, dass dieser Vorschlag die Art der Informationen erweitert, die Typ-Annotationen tragen, genauso wie PEP 702 sie erweitert, um Veraltungsinformationen aufzunehmen.

Annotated wurde zur Standardbibliothek hinzugefügt, um genau die Möglichkeit zu schaffen, zusätzliche Metadaten zu den Annotationen hinzuzufügen. Da die neue vorgeschlagene Klasse Doc eng mit Annotated verknüpft ist, ist es sinnvoll, dass sie im selben Modul liegt. Wenn Annotated in ein anderes Modul verschoben würde, wäre es sinnvoll, Doc mitzunehmen.

Mehrere Standards

Ein weiteres Argument dagegen wäre, dass es einen weiteren Standard schaffen würde und dass es bereits mehrere Konventionen für Docstrings gibt. Es könnte besser erscheinen, eine der derzeit bestehenden Standards zu formalisieren.

Nichtsdestotrotz deckt, wie oben erwähnt, keine dieser Konventionen die allgemeinen Nachteile eines Docstring-basierten Ansatzes ab, die dieser Vorschlag auf natürliche Weise löst.

Um eine Liste der Nachteile eines Docstring-basierten Ansatzes zu sehen, siehe den obigen Abschnitt in der **Begründung – Zusammenfassung**.

Ebenso ist zu sehen, dass in vielen Fällen ein neuer Standard, der neue Funktionen nutzt und mehrere Probleme früherer Methoden löst, lohnenswert sein kann. So wie bei der neuen pyproject.toml, dataclass_transform, dem neuen Typ-Pipe/Union (|) Operator und anderen Fällen.

Akzeptanz

Da dies ein neuer Standardvorschlag ist, wäre er nur sinnvoll, wenn er Interesse von der Community hätte.

Glücklicherweise gibt es bereits Interesse von mehreren Mainstream-Bibliotheken von mehreren Entwicklern und Teams, darunter FastAPI, Typer, SQLModel, Asyncer (vom Autor dieses Vorschlags), Pydantic, Strawberry (GraphQL) und andere.

Es gibt auch Interesse und Unterstützung von Dokumentationstools wie mkdocstrings, das bereits Unterstützung für eine frühere Version dieses Vorschlags hinzugefügt hat.

Alle kontaktierten CPython-Kernentwickler für frühes Feedback (mindestens 4) haben Interesse und Unterstützung für diesen Vorschlag gezeigt.

Editor-Entwickler (VS Code und PyCharm) haben Interesse gezeigt, während sie Bedenken hinsichtlich der Signatur-Ausführlichkeit des Vorschlags äußerten, aber nicht hinsichtlich der Implementierung (was sie am meisten betreffen würde). Und sie haben gezeigt, dass sie erwägen würden, Unterstützung dafür hinzuzufügen, wenn es ein offizieller Standard würde. In diesem Fall müssten sie nur Unterstützung für das Rendern hinzufügen, da die Unterstützung für die Bearbeitung, die für andere Standards normalerweise nicht vorhanden ist, bereits besteht, da sie bereits die Bearbeitung von Standard-Python-Syntax unterstützen.


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

Zuletzt geändert: 2025-05-06 20:44:17 GMT