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

Python Enhancement Proposals

PEP 682 – Format Specifier für Signed Zero

Autor:
John Belmonte <john at neggie.net>
Sponsor:
Mark Dickinson <dickinsm at gmail.com>
PEP-Delegate:
Mark Dickinson
Discussions-To:
Discourse thread
Status:
Final
Typ:
Standards Track
Erstellt:
29-Jan-2022
Python-Version:
3.11
Post-History:
08-Feb-2022
Resolution:
Discourse thread

Inhaltsverzeichnis

Zusammenfassung

Obwohl die Typen float und Decimal vorzeichenbehaftetes Null darstellen können, ist in vielen mathematischen Bereichen negatives Null überraschend oder unerwünscht – insbesondere im Kontext der Anzeige eines (oft gerundeten) numerischen Ergebnisses. Diese PEP schlägt eine Erweiterung der String-Format-Spezifikation vor, die es ermöglicht, negatives Null auf positives Null zu normalisieren.

Motivation

Hier ist negatives Null

>>> x = -0.
>>> x
-0.0

Beim Formatieren einer Zahl kann negatives Null durch Rundung entstehen. Unter der Annahme, dass die Absicht des Benutzers tatsächlich darin besteht, die Genauigkeit zu verwerfen, kann die Unterscheidung zwischen negativem und positivem Null des gerundeten Ergebnisses als unerwünschtes Artefakt betrachtet werden

>>> for x in (.002, -.001, .060):
...     print(f'{x: .1f}')
 0.0
-0.0
 0.1

Es gibt verschiedene Ansätze, um das Vorzeichen von negativem Null zu löschen. Dies kann ohne Bedingung durch Hinzufügen von positivem Null erreicht werden

>>> x = -0.
>>> x + 0.
0.0

Um negatives Null beim Formatieren zu normalisieren, ist eine redundante (und fehleranfällige) Vorabrundung der Eingabe erforderlich

>>> for x in (.002, -.001, .060):
...     print(f'{round(x, 1) + 0.: .1f}')
 0.0
 0.0
 0.1

Es gibt zahlreiche Beweise dafür, dass Programmierer unabhängig von der Sprache oft nach einer Möglichkeit suchen, negatives Null zu unterdrücken, und auf eine Vielzahl von Workarounds stoßen (Vorabrundung, Post-Regex usw.). Eine Stichprobe

Was wir stattdessen möchten, ist eine First-Class-Option zur Normalisierung von negativem Null, zusätzlich zu allem anderen, was die numerische String-Formatierung bereits bietet.

Begründung

Es gibt Anwendungsfälle, in denen negatives Null in der formatierten numerischen Ausgabe unerwünscht ist – wahrscheinlich ist es häufiger unerwünscht. Die Erweiterung der Format-Spezifikation ist der beste Weg, dies zu unterstützen, da die numerische Formatierung bereits Rundungen enthält und die Normalisierung von negativem Null nach der Rundung erfolgen muss.

Obwohl es möglich ist, eine Zahl vor der Formatierung vorzurunden und zu normalisieren, ist dies mühsam und fehleranfällig, wenn die Rundung nicht genau mit der der Format-Spezifikation übereinstimmt. Darüber hinaus müssten Funktionen, die die Formatierung umschließen, Format-Spezifikationen parsen, um die Präzisionsinformationen zu extrahieren. Betrachten Sie zum Beispiel, wie diese Dienstprogramm zur Formatierung eindimensionaler numerischer Arrays durch eine solche Vorabrundung kompliziert würde

def format_vector(v, format_spec='8.2f'):
    """Format a vector (any iterable) using given per-term format string."""
    return f"[{','.join(f'{term:{format_spec}}' for term in v)}]"

Bis heute scheint es keine andere weit verbreitete Sprache oder Bibliothek zu geben, die eine Formatierungsoption für negatives Null bietet. Die gleiche z-Option-Syntax und Semantik, die unten spezifiziert sind, wurden jedoch für C++ std::format() vorgeschlagen. Obwohl der Vorschlag für C++20 zurückgezogen wurde, wird ein Konsensvorschlag für C++23 versprochen. (Die ursprüngliche Feature-Anfrage, die diese PEP veranlasste, wurde ohne Kenntnis des C++-Vorschlags argumentiert.)

Als Rust-Entwickler diskutierten, ob negatives Null in der print-Ausgabe unterdrückt werden soll, führten sie eine kleine Umfrage in anderen Sprachen durch. Bemerkenswert ist, dass keine Sprache mit einer Option für die Handhabung von negativem Null erwähnt wurde.

Spezifikation

Ein optionales, literales z wird der Format Specification Mini-Language nach sign hinzugefügt

[[fill]align][sign][z][#][0][width][grouping_option][.precision][type]

wobei z für Gleitkomma-Darstellungstypen (f, g usw. gemäß der Dokumentation der Format-Spezifikation) zulässig ist. Unterstützung für z wird durch die Methode .__format__() jedes numerischen Typs bereitgestellt, sodass der Spezifizierer in f-Strings, der integrierten Funktion format() und str.format() verwendet werden kann.

Wenn z vorhanden ist, wird negatives Null (egal ob der ursprüngliche Wert oder das Ergebnis der Rundung) auf positives Null normalisiert.

Zusammenfassung

>>> x = -.00001
>>> f'{x:z.1f}'
'0.0'

>>> x = decimal.Decimal('-.00001')
>>> '{:+z.1f}'.format(x)
'+0.0'

Design Notes

Die Lösung muss opt-in sein, da wir das Verhalten von Programmen, die möglicherweise auf negatives Null beim Formatieren von Zahlen angewiesen sind oder darauf vertrauen, nicht ändern können.

Die vorgeschlagene Erweiterung ist bewusst [sign][z] und nicht [sign[z]]. Der Standard für sign (-) ist nicht allgemein bekannt oder explizit geschrieben, daher vermeidet dies, dass jeder ihn lernen muss, nur um die Option z zu verwenden.

Obwohl f-Strings, die integrierte Funktion format() und str.format() auf die neue Option zugreifen können, kann dies die %-Formatierung nicht. Es gibt bereits Präzedenzfälle für die Nicht-Erweiterung der %-Formatierung mit neuen Optionen, wie es bei der Option , der Fall war (PEP 378).

C99 printf verwendet bereits das Zeichen der Option z für einen anderen Zweck: die Qualifizierung des vorzeichenlosen Typs (u), um der Länge von size_t zu entsprechen. Da die Option für vorzeichenloses Null jedoch z für Ganzzahl-Darstellungstypen explizit verbietet, ist es möglich, die beiden Verwendungen zu disambiguieren, falls C diese neue Option übernehmen möchte.

Abwärtskompatibilität

Das neue Formatierungsverhalten ist opt-in, sodass die numerische Formatierung bestehender Programme nicht beeinträchtigt wird.

Wie man das lehrt

Ein typischer einführender Python-Kurs behandelt die String-Formatierung nicht im Detail. Für einen solchen Kurs müssten keine Anpassungen vorgenommen werden. Für einen Kurs, der sich detailliert mit der String-Format-Spezifikation befasst, sollte ein einzelnes Beispiel, das die Auswirkung der Option z auf einen negativen Wert zeigt, der durch die Formatierung auf Null gerundet wird, ausreichen. Für einen unabhängigen Entwickler, der die Funktion in fremdem Code antrifft, sollte ein Verweis auf den Abschnitt Format Specification Mini-Language des Bibliotheksreferenzhandbuchs genügen.

Referenzimplementierung

Eine Referenzimplementierung existiert unter Pull Request #30049.


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

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