PEP 750 – Template-Strings (t-strings) genehmigt
(peps.python.org)- PEP 750 führt in Python ein neues String-Literal ein: Template-Strings (
t"...") - Als verallgemeinerte Form von f-strings erzeugen sie den Typ
Templateund ermöglichen die Vorverarbeitung von Strings und eingebetteten Werten vor der Kombination - Nützlich für Web-Templates, Sicherheitsprüfungen, DSLs (Domain-Specific Languages) und mehr
Beziehung zu anderen PEPs
- f-strings wurden mit PEP 498 eingeführt, und ihre Syntax wurde in PEP 701 erweitert
- PEP 501 schlug allgemeine Template-Strings (
i-string) vor, wurde aber zurückgestellt - Das aktuelle PEP 750 ist eine vereinfachte und verallgemeinerte Form von PEP 501 und entwickelt die bestehenden Ideen weiter
Motivation und Notwendigkeit
- f-strings sind einfach, können eingebettete Werte aber nicht vorab verarbeiten, was Sicherheitsprobleme verursachen kann
- Es besteht das Risiko von Sicherheitslücken wie SQL-Injection und XSS-Angriffen
- Mit Template-Strings lassen sich eingebettete Werte vorab verarbeiten und dadurch sicherer verwenden
Beispiel:
evil = "<script>alert('evil')</script>"template = t"<p>{evil}</p>"assert html(template) == "<p><script>alert('evil')</script></p>"
Spezifikation der Template-Strings
Template-String-Literale
- Werden mit dem Präfix
toderTdefiniert - Werden zu
string.templatelib.Templateausgewertet - Unterstützen eine f-string-ähnliche Syntax, auch verschachtelt
- Können mit dem Präfix
rkombiniert werden (rt,tr) - Können nicht mit den Präfixen
uoderbkombiniert werden - f-strings und Template-Strings können nicht gemischt verwendet werden
Typ Template
- Ein unveränderlicher Typ mit den folgenden Eigenschaften:
strings: Tupel von String-Fragmenteninterpolations: Tupel von Einbettungsobjektenvalues: Wertetupel der Einbettungen__iter__(): Iterator, der Strings und Einbettungen der Reihe nach zurückgibt
Typ Interpolation
value: das ausgewertete Ergebnisexpression: die ursprüngliche String-Darstellung des Einbettungsausdrucksconversion: Art der Konvertierung (r,s,aoder None)format_spec: Format-String
Beispiel:
name = "World"template = t"Hello {name!r}"assert template.interpolations[0].conversion == "r"
Debug-Spezifizierer =
t"{value=}"wird alst"value={value!r}"interpretiert- Auch Leerzeichen bleiben unverändert erhalten (
t"{value = }"→"value = {value!r}")
Verkettung von Template-Strings
- Mit dem
+-Operator könnenTemplateundstrsowie zweiTemplate-Objekte kombiniert werden - Das Ergebnis einer Verkettung ist immer vom Typ
Template - Auch implizite String-Verkettung ist möglich (
t"Hello " t"World")
Verarbeitung von Template-Strings
Beispiel: Funktion zur Groß-/Kleinschreibung
def lower_upper(template):parts = []for s in template:if isinstance(s, str): parts.append(s.lower())else: parts.append(str(s.value).upper())
return "".join(parts)
Beispiel: Verarbeitung wie bei f-strings implementieren
- Mit einer Funktion
f()lässt sich dasselbe Ergebnis wie mit f-strings erzeugen
Beispiel: strukturiertes Logging
- Mit Template-Strings können Log-Nachrichten und strukturierte Werte gleichzeitig ausgegeben werden
- Kann mit
StructuredMessageoder einer Unterklasse vonlogging.Formatterimplementiert werden
Beispiel: HTML-Template-Verarbeitung
- Die Funktion
html()behandelt Inhalte je nach Einfügeposition passend per Escaping oder als Attribut - Auch verschachtelte Templates werden unterstützt
Fortgeschrittene Nutzungsmuster
- Die Verwendung von strukturellem Pattern Matching (
match-Anweisung) wird empfohlen - Statische Strings können als Cache-Schlüssel dienen und effiziente Memoization ermöglichen
- Verarbeitung durch Parsen in Zwischenrepräsentationen wie AST ist möglich
- Für Lazy- oder Async-Auswertung können
lambdaundawaitverwendet werden
Beziehung zwischen Template-Strings und bestehenden Format-Strings
- Template-Funktionen lassen sich ähnlich wie mit bestehendem
.format()definieren - Auch
from_format()zum Parsen externer Strings und zur Umwandlung inTemplateist möglich
Kompatibilität, Sicherheit und Lernen
- In älteren Python-Versionen kann ein Syntaxfehler auftreten
- Die Verarbeitung über Templates erhöht die Sicherheit
- Durch die f-string-ähnliche Syntax ist der Einstieg einfach
Warum ein neuer Template-Ansatz?
- Bestehende Templates wie Jinja richten sich an Nutzeranpassungen oder Designer
- Es braucht Unterstützung auf Sprachebene in Python, damit Entwickler Templates direkt handhaben können
- So lassen sich Vorteile wie Ausdrucksstärke und Typprüfung nutzen
Zusammenfassung typischer Muster
- Strukturelles Pattern Matching und Matching auf Untereigenschaften
- Wiederverwendung von Templates wie Funktionen
- Unterstützung verschachtelter Templates
- Unterstützung für Lazy-/Async-Auswertung
- Cache-Optimierung durch Trennung von statischen und dynamischen Teilen
Weitere Designüberlegungen
- Templates werden nicht in Strings umgewandelt;
__str__()ist nicht implementiert - Die zugehörigen Klassen werden im Modul
string.templatelibbereitgestellt TemplateundInterpolationwerden anhand der Objektidentität verglichen- Die Operatoren
==und<werden nicht unterstützt
Referenzimplementierung und Beispiele
- CPython-Implementierung
- Beispiele und Tests verfügbar
Abgelehnte Ideen
- Verwendung beliebiger Präfixe (
my_tag"...") - Verzögerte Auswertung aller Einbettungsausdrücke
- Implementierung als Protokoll
- Neudefinition von
__eq__und__hash__ - Vollständige Wiederherstellung des Original-Strings
- Hinzufügen eines Typs
Decoded - Unterstützung binärer Template-Strings
- Möglichkeit zur Angabe von Formatarten ("html", "sql" usw.)
- Einschränkung der String-Verkettung
- Zulassen beliebiger Konverter (
!x)
3 Kommentare
Die zufriedenstellendste Formatierung gibt es meiner Meinung nach nur in JS und Python. Andere Sprachen sind eher so na ja...
Es sollte einen klaren und möglichst nur einen offensichtlichen Weg geben, etwas zu tun. (There should be one-- and preferably only one --obvious way to do it.)
Hacker-News-Kommentare
Es ist interessant, wie verschiedene Sprachen mit String-Formatierung umgehen
.format(), f-strings und t-stringsNick Humrich ist einer der Autoren, die PEP 501 umgeschrieben und t-strings eingeführt haben, und freut sich sehr über die Annahme dieses PEP
Ich bin mir nicht sicher, ob ein Feature auf Sprachebene wirklich wertvoll ist
Ich mag f-strings, aber sie haben das Problem, dass man die Auswertung nicht verzögern kann
str.formatverwenden muss, und das ist unpraktischAls Maintainer von lit-html finde ich die Ähnlichkeiten zu den getaggten Template-Literalen von JavaScript interessant
Template-Klasse von Python die JavaScript-Tag-Funktion und ihre Argumente trennt, ist ungewöhnlichhtml()unnötig seinIch hoffe, dass das, was getaggte Template-Literale in JavaScript für automatisches HTML-Escaping oder SQL-Parametrisierung nützlich macht, auch auf Python übertragbar ist
Es gibt die Meinung, Python verwandle sich in PHP
string.formathalte ich für optimal, und%ist ebenfalls akzeptabel, da es schon lange verwendet wirdUnzufriedenheit darüber, dass der Sprache ständig Neues hinzugefügt wird
Die Meinung, dass dieses PEP dem P1819 von C++ ähnelt
Die Meinung, dass der Code im PEP zu ausführlich ist