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

Python Enhancement Proposals

PEP 536 – Finale Grammatik für Literal String Interpolation

Autor:
Philipp Angerer <phil.angerer at gmail.com>
Status:
Zurückgezogen
Typ:
Standards Track
Erstellt:
11-Dez-2016
Python-Version:
3.7
Post-History:
18-Aug-2016, 23-Dez-2016, 15-Mrz-2019
Resolution:
Discourse-Nachricht

Inhaltsverzeichnis

Zusammenfassung

PEP 498 führte Literal String Interpolation (oder „f-strings“) ein. Die Ausdrucksteile dieser Literale unterliegen jedoch bestimmten Einschränkungen. Dieser PEP schlägt eine formale Grammatik vor, die diese Einschränkungen aufhebt und „f-strings“ zu „f expressions“ oder f-Literalen aufwertet.

Dieser PEP erweitert die von PEP 498 eingeführten f-strings. Daher erfordert dieser Text Vertrautheit mit PEP 498.

Rücknahme eines PEP

Dieser PEP wurde zugunsten von PEP 701 zurückgezogen. PEP 701 behandelt alle wichtigen Punkte dieses PEP.

Terminologie

Dieser Text wird die bestehende Grammatik als „f-strings“ und die vorgeschlagene als „f-literale“ bezeichnen.

Darüber hinaus wird er die mit {} umschlossenen Ausdrücke in f-literalen/f-strings als „Ausdrucksteile“ und den statischen Zeicheninhalt um sie herum als „Zeichenkettenanteile“ bezeichnen.

Motivation

Die aktuelle Implementierung von f-strings in CPython stützt sich auf die bestehende String-Parsing-Maschinerie und eine Nachbearbeitung seiner Tokens. Dies führt zu mehreren Einschränkungen für mögliche Ausdrücke, die in f-strings verwendet werden können.

  1. Es ist unmöglich, das Anführungszeichen, das den f-string umschließt, innerhalb des Ausdrucksteils zu verwenden.
    >>> f'Magic wand: { bag['wand'] }'
                                 ^
    SyntaxError: invalid syntax
    
  2. Ein zuvor erwogener Ausweg würde zu Escape-Sequenzen in ausgeführtem Code führen und ist in f-strings verboten.
    >>> f'Magic wand { bag[\'wand\'] } string'
    SyntaxError: f-string expression portion cannot include a backslash
    
  3. Kommentare sind selbst in mehrzeiligen f-strings verboten.
    >>> f'''A complex trick: {
    ... bag['bag']  # recursive bags!
    ... }'''
    SyntaxError: f-string expression part cannot include '#'
    
  4. Ausdrucksteile müssen ':' und '!' in geschweifte Klammern einschließen.
    >>> f'Useless use of lambdas: { lambda x: x*2 }'
    SyntaxError: unexpected EOF while parsing
    

Diese Einschränkungen dienen aus Sicht des Sprachbenutzers keinem Zweck und können durch die Vergabe von f-literalen an eine reguläre Grammatik ohne Ausnahmen und deren Implementierung mit dediziertem Parsing-Code aufgehoben werden.

Begründung

Die in der Motivation genannten Einschränkungen sind nicht offensichtlich und kontraintuitiv, es sei denn, der Benutzer ist mit den Implementierungsdetails von f-literalen vertraut.

Wie erwähnt, erlaubte eine frühere Version von PEP 498 Escape-Sequenzen überall in f-strings, auch als Mittel zur Kodierung der Klammern, die die Ausdrucksteile umschließen, und in deren Code. Diese wären vor dem Parsen des Codes erweitert worden, was mehrere wichtige Auswirkungen gehabt hätte:

#. Es wäre für menschliche Leser nicht klar, welche Teile Ausdrücke und welche Zeichenketten sind. Großartiges Material für eine „obskure/unterhändische Python-Herausforderung“. #. Syntax-Highlighter sind gut im Parsen von verschachtelter Grammatik, aber nicht im Erkennen von Escape-Sequenzen. ECMAScript 2016 (JavaScript) erlaubt Escape-Sequenzen in seinen Bezeichnern [1] und der Autor kennt keinen Syntax-Highlighter, der in der Lage wäre, Code, der diese verwendet, korrekt hervorzuheben.

Folglich wären die Ausdrucksteile mit und ohne Hilfe von Syntaxhervorhebung schwerer zu erkennen. Mit der neuen Grammatik ist es einfach, Syntax-Highlighter zu erweitern, um f-literale korrekt zu parsen und anzuzeigen.

f'Magic wand: {bag['wand']:^10}'

Die Hervorhebung von Ausdrucksteilen mit möglichen Escape-Sequenzen würde bedeuten, eine modifizierte Kopie aller Regeln der vollständigen Ausdrucksgrammatik zu erstellen, die die Möglichkeit von Escape-Sequenzen in Schlüsselwörtern, Begrenzern und allen anderen Sprachsyntaktiken berücksichtigt. Eine solche Duplizierung würde eine Eskalationstiefe von einer Ebene ergeben und für tiefere Eskalationen in einem rekursiven f-literal wiederholt werden müssen. Dies ist der Fall, da keine dem Autor bekannte Hervorhebungs-Engine das Erweitern von Escape-Sequenzen unterstützt, bevor Regeln auf einen bestimmten Kontext angewendet werden. Verschachtelte Kontexte sind jedoch ein Standardmerkmal aller Hervorhebungs-Engines.

Vertrautheit spielt ebenfalls eine Rolle: Die willkürliche Verschachtelung von Ausdrücken ohne Erweiterung von Escape-Sequenzen ist in jeder anderen Sprache verfügbar, die eine String-Interpolationsmethode verwendet, die Ausdrücke anstelle von nur Variablennamen nutzt. [2]

Spezifikation

PEP 498 spezifizierte f-strings wie folgt, setzt jedoch Einschränkungen

f ' <text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> ... '

Alle im PEP genannten Einschränkungen werden von f-literalen aufgehoben, wie unten erläutert.

  1. Ausdrucksteile können nun Strings enthalten, die mit derselben Art von Anführungszeichen begrenzt sind, die zur Begrenzung des f-literals verwendet werden.
  2. Backslashes können nun innerhalb von Ausdrücken erscheinen, genau wie überall sonst im Python-Code. Bei verschachtelten Strings innerhalb von f-literalen werden Escape-Sequenzen erweitert, wenn der innerste String ausgewertet wird.
  3. Kommentare, die das Zeichen '#' verwenden, sind nur in mehrzeiligen f-literalen möglich, da Kommentare durch das Ende der Zeile beendet werden (was das Schließen eines einzeiligen f-literals unmöglich macht).
  4. Ausdrucksteile können ':' oder '!' enthalten, wo immer dies syntaktisch gültig ist. Dem ersten ':' oder '!', das nicht Teil eines Ausdrucks ist, muss ein gültiger Koerzions- oder Formatierungs-Spezifizierer folgen.

Eine verbleibende Einschränkung, die von PEP 498 nicht explizit erwähnt wird, sind Zeilenumbrüche in Ausdrucksteilen. Da Strings, die durch einfache '- oder "-Zeichen begrenzt sind, als einzeilig erwartet werden, bleiben Zeilenumbrüche in Ausdrucksteilen von einzeiligen Strings illegal.

Hinweis

Ist die Aufhebung der Einschränkungen ausreichend oder sollten wir eine vollständigere Grammatik spezifizieren?

Abwärtskompatibilität

f-literale sind vollständig abwärtskompatibel zu f-strings und erweitern die als legal betrachtete Syntax.

Referenzimplementierung

TBD

Referenzen


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

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