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

Python Enhancement Proposals

PEP 378 – Format-Spezifizierer für Tausendertrennzeichen

Autor:
Raymond Hettinger <python at rcn.com>
Status:
Final
Typ:
Standards Track
Erstellt:
12-März-2009
Python-Version:
2.7, 3.1
Post-History:
12-März-2009

Inhaltsverzeichnis

Motivation

Bietet eine einfache, nicht-lokalisierungsabhängige Möglichkeit, eine Zahl mit einem Tausendertrennzeichen zu formatieren.

Das Hinzufügen von Tausendertrennzeichen ist eine der einfachsten Möglichkeiten, die Ausgabe eines Programms zu humanisieren und deren professionelles Erscheinungsbild und Lesbarkeit zu verbessern.

In der Finanzwelt ist die Ausgabe mit Tausendertrennzeichen die Norm. Finanznutzer und nicht-professionelle Programmierer empfinden den Locale-Ansatz als frustrierend, obskur und nicht offensichtlich.

Das `locale`-Modul birgt zwei weitere Herausforderungen. Erstens ist es eine globale Einstellung und nicht für Multi-Thread-Anwendungen geeignet, die Anfragen in mehreren Locales bedienen müssen. Zweitens kann der Name eines relevanten Locales (wie „de_DE“) von Plattform zu Plattform variieren oder gar nicht definiert sein. Die Dokumentation des `locale`-Moduls beschreibt diese und viele andere Herausforderungen im Detail.

Es ist nicht das Ziel, das `locale`-Modul zu ersetzen, Internationalisierungsaufgaben durchzuführen oder jede mögliche Konvention zu berücksichtigen. Solche Aufgaben sind besser für robuste Werkzeuge wie Babel geeignet. Stattdessen ist das Ziel, eine gängige, alltägliche Aufgabe für viele Benutzer zu erleichtern.

Hauptvorschlag (von Alyssa Coghlan, ursprünglich Vorschlag I genannt)

Ein Komma wird zur Mini-Sprache des `format()`-Spezifizierers hinzugefügt.

[[fill]align][sign][#][0][width][,][.precision][type]

Die Option ‚,‘ gibt an, dass Kommas in der Ausgabe als Tausendertrennzeichen enthalten sein sollen. Wie bei Locales, die keinen Punkt als Dezimaltrennzeichen verwenden, müssen Locales, die eine andere Konvention für die Zifferntrennung verwenden, das `locale`-Modul verwenden, um die entsprechende Formatierung zu erhalten.

Der Vorschlag funktioniert gut mit Floats, Integern und Dezimalzahlen. Er ermöglicht auch einen einfachen Ersatz für andere Trennzeichen. Zum Beispiel

format(n, "6,d").replace(",", "_")

Diese Technik ist vollständig allgemein, aber sie ist in dem einen Fall umständlich, in dem die Kommas und Punkte vertauscht werden müssen.

format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".")

Das Argument width bedeutet die Gesamtlänge einschließlich der Kommas und des Dezimalpunkts.

format(1234, "08,d")     -->    '0001,234'
format(1234.5, "08,.1f") -->    '01,234.5'

Die Option ‚,‘ ist wie oben für die Typen ‚d‘, ‚e‘, ‚f‘, ‚g‘, ‚E‘, ‚G‘, ‚%‘, ‚F‘ und ‚‘ definiert. Um zukünftige Erweiterungen zu ermöglichen, ist sie für andere Typen undefiniert: binär, oktal, hexadezimal, Zeichen usw.

Dieser Vorschlag hat den Vorteil, einfacher als der alternative Vorschlag zu sein, ist aber weitaus weniger flexibel und erfüllt sofort die Bedürfnisse von weniger Benutzern. Es wird erwartet, dass eine andere Lösung für die Angabe alternativer Trennzeichen entstehen wird.

Aktuelle Version der Mini-Sprache

Recherche zu anderen Sprachen

Beim Durchsuchen des Webs habe ich festgestellt, dass Tausendertrennzeichen normalerweise eines der folgenden sind: KOMMA, PUNKT, LEERZEICHEN, APOSTROPH oder UNTERSTRICH.

C-Sharp bietet beide Stile (Bildformatierung und Typenspezifizierer). Der Typenspezifiziereransatz ist lokalisierungsabhängig. Die Bildformatierung bietet nur ein KOMMA als Tausendertrennzeichen.

String.Format("{0:n}", 12400)     ==>    "12,400"
String.Format("{0:0,0}", 12400)   ==>    "12,400"

Common Lisp verwendet einen DOPPELPUNKT vor dem Dezimaltyp-Spezifizierer ~D, um ein KOMMA als Tausendertrennzeichen auszugeben. Die allgemeine Form von ~D lautet ~mincol,padchar,commachar,commaintervalD. Das padchar ist standardmäßig LEERZEICHEN. Das commachar ist standardmäßig KOMMA. Das commainterval ist standardmäßig drei.

(format nil "~:D" 229345007)   =>   "229,345,007"
  • Die ADA-Sprache erlaubt UNTERSTRICH in ihren numerischen Literalen.

Visual Basic und seine Verwandten (wie MS Excel) verwenden einen völlig anderen Stil und haben extrem flexible benutzerdefinierte Format-Spezifizierer wie

"_($* #,##0_)".

COBOL verwendet Bildklauseln wie

PICTURE $***,**9.99CR

Java bietet eine Decimal.Format Klasse, die Bildmuster verwendet (eines für positive Zahlen und optional eines für negative) wie: "#,##0.00;(#,##0.00)". Sie erlaubt willkürliche Gruppierungen, einschließlich Hunderter und Zehntausender sowie ungleichmäßige Gruppierungen. Die Sonderzeichen des Musters sind nicht lokalisiert (sie verwenden einen PUNKT als Dezimaltrennzeichen und ein KOMMA als Gruppentrennzeichen). Der Benutzer kann einen alternativen Zeichensatz über das DecimalFormatSymbols-Objekt des Formatierers bereitstellen.

Alternativer Vorschlag (von Eric Smith, ursprünglich Vorschlag II genannt)

Machen Sie sowohl das Tausender- als auch das Dezimaltrennzeichen benutzerdefinierbar, aber nicht lokalisierungsabhängig. Der Einfachheit halber beschränken Sie die Auswahl auf KOMMA, PUNKT, LEERZEICHEN, APOSTROPH oder UNTERSTRICH. Das LEERZEICHEN kann entweder U+0020 oder U+00A0 sein.

Immer wenn einem Trennzeichen eine Präzision folgt, handelt es sich um ein Dezimaltrennzeichen und ein optionales davor liegendes Trennzeichen ist ein Tausendertrennzeichen. Wenn die Präzision fehlt, bedeutet ein alleinstehender Spezifizierer ein Tausendertrennzeichen.

[[fill]align][sign][#][0][width][tsep][dsep precision][type]

Beispiele

format(1234, "8.1f")     -->    '  1234.0'
format(1234, "8,1f")     -->    '  1234,0'
format(1234, "8.,1f")    -->    ' 1.234,0'
format(1234, "8 ,f")     -->    ' 1 234,0'
format(1234, "8d")       -->    '    1234'
format(1234, "8,d")      -->    '   1,234'
format(1234, "8_d")      -->    '   1_234'

Dieser Vorschlag erfüllt die meisten Bedürfnisse, geht aber auf Kosten einer etwas höheren Parsing-Anstrengung. Nicht jede mögliche Konvention ist abgedeckt, aber mindestens eine der Optionen (Leerzeichen oder Unterstriche) sollte für Menschen aus vielen verschiedenen Hintergründen lesbar, verständlich und nützlich sein.

Wie in den Beispielen gezeigt, bedeutet das width-Argument die Gesamtlänge einschließlich der Tausendertrennzeichen und Dezimaltrennzeichen.

Für das `locale`-Modul wird keine Änderung vorgeschlagen.

Das Tausendertrennzeichen ist wie oben für die Typen ‚d‘, ‚e‘, ‚f‘, ‚g‘, ‚%‘, ‚E‘, ‚G‘ und ‚F‘ definiert. Um zukünftige Erweiterungen zu ermöglichen, ist es für andere Typen undefiniert: binär, oktal, hexadezimal, Zeichen usw.

Der Nachteil dieses alternativen Vorschlags ist die Schwierigkeit, mental zu parsen, ob ein einzelnes Trennzeichen ein Tausender- oder Dezimaltrennzeichen ist. Vielleicht ist es zu obskur, das Dezimaltrennzeichen mit dem Präzisionsspezifizierer zu verknüpfen.

Kommentar

  • Einige Kommentatoren mögen die Idee von Format-Strings überhaupt nicht und finden sie unleserlich. Vorgeschlagene Alternativen sind der COBOL-Stil PICTURE-Ansatz oder eine Hilfsfunktion mit Schlüsselwortargumenten für jede mögliche Kombination.
  • Einige Newsgroup-Antworten besagen, dass es keinen Platz für Skripte gibt, die nicht internationalisiert sind, und dass es ein Rückschritt ist, eine einfache Möglichkeit zu bieten, eine bestimmte Wahl fest zu verdrahten (wodurch der Anreiz verringert wird, einen lokalisierungsabhängigen Ansatz zu verwenden).
  • Eine andere Überlegung ist, dass das Einbetten einer bestimmten Konvention in einzelne Format-Strings es schwierig macht, diese Konvention später zu ändern. Es wurde keine praktikable Alternative vorgeschlagen, aber die allgemeine Idee ist, die Konvention einmal festzulegen und sie überall anwenden zu lassen (andere Kommentierten, dass `locale` bereits eine Möglichkeit bietet, dies zu tun).
  • Es gibt einige Präzedenzfälle für die Gruppierung von Ziffern im Bruchteil einer Gleitkommazahl, aber diese PEP wagt sich nicht in dieses Territorium. Nur Ziffern links vom Dezimalpunkt werden gruppiert. Dies schließt zukünftige Erweiterungen nicht aus; es konzentriert sich lediglich auf eine einzige, allgemein nützliche Erweiterung der Formatierungssprache.
  • James Knight bemerkte, dass indische/pakistanische Zahlensysteme nach Hunderten gruppieren. Ben Finney wies darauf hin, dass Chinesen nach Zehntausendern gruppieren. Eric Smith wies darauf hin, dass diese bereits vom „n“-Spezifizierer im `locale`-Modul (wenn auch nur für Ganzzahlen) behandelt werden. Diese PEP versucht nicht, all diese Möglichkeiten zu unterstützen. Sie konzentriert sich auf eine einzige, relativ gängige Gruppierungskonvention, die eine schnelle Verbesserung der Lesbarkeit in vielen (wenn auch nicht allen) Kontexten bietet.

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

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