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

Python Enhancement Proposals

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

Inhaltsverzeichnis

Zusammenfassung

Dieses PEP beschreibt eine einfachere String-Substitutionsfunktion, auch bekannt als String-Interpolation. Dieses PEP ist in zweierlei Hinsicht „einfacher“

  1. Die aktuelle String-Substitutionsfunktion von Python (d.h. %-Substitution) ist kompliziert und fehleranfällig. Dieses PEP ist auf Kosten einiger Ausdrucksstärke einfacher.
  2. 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:

  1. $$ ist eine Escape-Sequenz; sie wird durch ein einzelnes $ ersetzt.
  2. $identifier nennt 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.
  3. ${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 der Template substituiert werden. Wenn Platzhalter vorhanden sind, die nicht im Mapping vorhanden sind, wird ein KeyError ausgelöst.
  • safe_substitute(). Dies ist ähnlich zur substitute()-Methode, außer dass niemals KeyErrors ausgelö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


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

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