PEP 292 – Einfachere String-Substitutionen
- Autor:
- Barry Warsaw <barry at python.org>
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 18. Juni 2002
- Python-Version:
- 2.4
- Post-History:
- 18. Juni 2002, 23. März 2004, 22. August 2004
- Ersetzt:
- 215
Zusammenfassung
Dieses PEP beschreibt eine einfachere String-Substitutionsfunktion, auch bekannt als String-Interpolation. Dieses PEP ist in zweierlei Hinsicht „einfacher“
- Die aktuelle String-Substitutionsfunktion von Python (d.h.
%-Substitution) ist kompliziert und fehleranfällig. Dieses PEP ist auf Kosten einiger Ausdrucksstärke einfacher. - PEP 215 schlug eine alternative String-Interpolationsfunktion vor, die ein neues
$-Präfix für Strings einführte. PEP 292 ist einfacher als dies, da es keine Syntaxänderungen beinhaltet und viel einfachere Regeln dafür hat, welche Substitutionen im String auftreten können.
Begründung
Python unterstützt derzeit eine String-Substitutionssyntax, die auf dem printf() von C basiert, Zeichen [1]. Obwohl recht reichhaltig, sind %-Formatierungszeichen auch fehleranfällig, selbst für erfahrene Python-Programmierer. Ein häufiger Fehler ist das Weglassen des abschließenden Formatzeichens, z. B. des 's' in "%(name)s".
Darüber hinaus sind die Regeln dafür, was auf ein %-Zeichen folgen kann, recht komplex, während die übliche Anwendung selten eine solche Komplexität benötigt. Die meisten Skripte müssen eine String-Interpolation durchführen, aber die meisten davon verwenden einfache 'Stringifizierungs'-Formate, d. h. %s oder %(name)s. Diese Form sollte einfacher und weniger fehleranfällig gestaltet werden.
Ein einfacherer Vorschlag
Wir schlagen die Hinzufügung einer neuen Klasse namens Template vor, die im string-Modul leben wird. Die Template-Klasse unterstützt neue Regeln für die String-Substitution; ihr Wert enthält Platzhalter, die mit dem Zeichen $ eingeführt werden. Die folgenden Regeln für $-Platzhalter gelten:
$$ist eine Escape-Sequenz; sie wird durch ein einzelnes$ersetzt.$identifiernennt einen Substitutionsplatzhalter, der einem Mapping-Schlüssel von "identifier" entspricht. Standardmäßig muss "identifier" ein Python-Identifier sein, wie in [2] definiert. Das erste Nicht-Identifier-Zeichen nach dem Zeichen$beendet diese Platzhalterspezifikation.${identifier}ist äquivalent zu$identifier. Es ist erforderlich, wenn gültige Identifier-Zeichen auf den Platzhalter folgen, aber nicht Teil des Platzhalters sind, z. B."${noun}ification".
Wenn das Zeichen $ am Ende der Zeile erscheint oder von einem anderen Zeichen als den oben beschriebenen gefolgt wird, wird zur Interpolationszeit ein ValueError ausgelöst. Werte in einem Mapping werden automatisch in Strings konvertiert.
Keine anderen Zeichen haben eine besondere Bedeutung, jedoch ist es möglich, von der Template-Klasse abzuleiten, um andere Substitutionsregeln zu definieren. Beispielsweise könnte eine abgeleitete Klasse Punkte im Platzhalter zulassen (z. B. um eine Art dynamischen Namespace und Attributpfad-Lookup zu unterstützen) oder ein anderes Trennzeichen als $ definieren.
Sobald die Template erstellt wurde, können Substitutionen durch Aufrufen einer von zwei Methoden durchgeführt werden:
substitute(). Diese Methode gibt einen neuen String zurück, der sich ergibt, wenn die Werte eines Mappings für die Platzhalter in derTemplatesubstituiert werden. Wenn Platzhalter vorhanden sind, die nicht im Mapping vorhanden sind, wird einKeyErrorausgelöst.safe_substitute(). Dies ist ähnlich zursubstitute()-Methode, außer dass niemalsKeyErrorsausgelöst werden (wegen fehlender Platzhalter im Mapping). Wenn ein Platzhalter fehlt, erscheint der ursprüngliche Platzhalter im Ergebnisstring.Hier sind einige Beispiele:
>>> from string import Template >>> s = Template('${name} was born in ${country}') >>> print s.substitute(name='Guido', country='the Netherlands') Guido was born in the Netherlands >>> print s.substitute(name='Guido') Traceback (most recent call last): [...] KeyError: 'country' >>> print s.safe_substitute(name='Guido') Guido was born in ${country}
Die Signatur von substitute() und safe_substitute() erlaubt die Übergabe des Mappings von Platzhaltern zu Werten, entweder als einzelnes dictionary-ähnliches Objekt im ersten positionsgebundenen Argument oder als Schlüsselwortargumente, wie oben gezeigt. Die genauen Details und Signaturen dieser beiden Methoden sind der Dokumentation der Standardbibliothek vorbehalten.
Warum $ und geschweifte Klammern?
Der BDFL hat es am besten ausgedrückt [3]: „Das $ bedeutet „Substitution“ in so vielen Sprachen außer Perl, dass ich mich frage, wo du warst. […] Wir kopieren das aus der Shell.“
Daher werden die Substitutionsregeln aufgrund der Ähnlichkeit mit so vielen anderen Sprachen gewählt. Dies macht die Substitutionsregeln einfacher zu lehren, zu lernen und sich zu merken.
Vergleich mit PEP 215
PEP 215 beschreibt einen alternativen Vorschlag für die String-Interpolation. Im Gegensatz zu diesem PEP schlägt dieses PEP keine neue Syntax für Python vor. Alle vorgeschlagenen neuen Funktionen sind in einem neuen Bibliotheksmodul enthalten. PEP 215 schlägt eine neue String-Präfix-Darstellung wie $"" vor, die Python signalisiert, dass ein neuer String-Typ vorhanden ist. $-Strings müssten mit den bestehenden r- und u-Präfixen interagieren, wodurch sich die Anzahl der String-Präfix-Kombinationen im Wesentlichen verdoppelt.
PEP 215 erlaubt auch beliebige Python-Ausdrücke innerhalb der $-Strings, sodass Sie Dinge tun könnten wie
import sys
print $"sys = $sys, sys = $sys.modules['sys']"
was zurückgeben würde
sys = <module 'sys' (built-in)>, sys = <module 'sys' (built-in)>
Es ist allgemein anerkannt, dass die Regeln in PEP 215 sicher sind, in dem Sinne, dass sie keine neuen Sicherheitsprobleme einführen (siehe PEP 215, „Sicherheitsfragen“ für Details). Die Regeln sind jedoch immer noch recht komplex und erschweren es, den Substitutionsplatzhalter im ursprünglichen $-String zu erkennen.
Das Interessante ist, dass die in diesem PEP definierte Template-Klasse für Vererbung konzipiert ist und mit etwas zusätzlicher Arbeit die Funktionalität von PEP 215 mit der bestehenden Python-Syntax unterstützt werden kann.
Zum Beispiel könnte man Unterklassen von Template und dict definieren, die eine komplexere Platzhaltersyntax und ein Mapping zulassen, das diese Platzhalter auswertet.
Internationalisierung
Die Implementierung unterstützt Internationalisierung, indem sie den ursprünglichen Template-String im Attribut template der Template-Instanz aufzeichnet. Dieses Attribut dient als Schlüssel für die Suche in einem gettext-basierten Katalog. Es liegt in der Verantwortung der Anwendung, den resultierenden String zurück in eine Template für die Substitution zu verwandeln.
Die Template-Klasse wurde jedoch so konzipiert, dass sie in einer internationalisierten Anwendung intuitiver funktioniert, indem sie das Mischen von Template und Unicode-Unterklassen unterstützt. So könnte eine internationalisierte Anwendung eine anwendungsspezifische Unterklasse erstellen, die mehrfach von Template und Unicode erbt, und Instanzen dieser Unterklasse als Schlüssel für den gettext-Katalog verwenden. Darüber hinaus könnte die Unterklasse die spezielle Methode __mod__() entweder in .substitute() oder .safe_substitute() umbenennen, um eine traditionellere String-/Unicode-ähnliche %-Operator-Substitutionssyntax bereitzustellen.
Referenzimplementierung
Die Implementierung [4] wurde in den Python 2.4 Quellcodebaum integriert.
Referenzen
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0292.rst
Zuletzt geändert: 2025-02-01 08:55:40 GMT