Ist es möglich, eine teilweise Zeichenfolgenformatierung mit den erweiterten Zeichenfolgenformatierungsmethoden durchzuführen, ähnlich wie bei der Zeichenfolgenvorlagenfunktion safe_substitute()
?
Beispielsweise:
s = '{foo} {bar}'
s.format(foo='FOO') #Problem: raises KeyError 'bar'
python
string-formatting
P3trus
quelle
quelle
{bar:1.2f}
__missing__()
, geben Sie eine Instanz einer benutzerdefinierten Klasse zurück, die so überschrieben__format__()
wird, dass der ursprüngliche Platzhalter einschließlich der Formatspezifikation zurückgegeben wird. Proof of Concept: ideone.com/xykV7RWenn Sie wissen, in welcher Reihenfolge Sie die Dinge formatieren:
Verwenden Sie es so:
Sie können nicht angeben
foo
undbar
gleichzeitig - Sie müssen es nacheinander tun.quelle
s.format(foo='FOO',bar='BAR')
dann habe ich immer noch'FOO {bar}'
, egal was passiert. Könnten Sie es klarstellen?Sie können die
partial
Funktion verwenden,functools
die kurz und am besten lesbar ist und auch die Absicht des Codierers beschreibt:quelle
python from functool import partial s = "{foo} {bar}".format s_foo = partial(s, foo="FOO") print(s_foo(bar="BAR")) # FOO BAR print(s(foo="FOO", bar="BAR")) # FOO BAR
partial()
wird mir nicht helfen, wenn ich etwas mit der teilweise formatierten Zeichenfolge (das heißt"FOO {bar}"
) verarbeiten muss."{foo} {{bar}}".format(foo="{bar}").format(bar="123")
aus den anderen Beispielen. Ich würde erwarten,"{bar} 123"
aber sie geben aus"123 123"
.Diese Einschränkung von
.format()
- die Unfähigkeit, teilweise Substitutionen vorzunehmen - hat mich nervt.Nachdem ich das Schreiben einer benutzerdefinierten
Formatter
Klasse wie in vielen Antworten beschrieben beschrieben und sogar die Verwendung von Paketen von Drittanbietern wie lazy_format in Betracht gezogen hatte , entdeckte ich eine viel einfachere integrierte Lösung: VorlagenzeichenfolgenEs bietet ähnliche Funktionen, bietet aber auch eine gründliche
safe_substitute()
Methode zur teilweisen Substitution . Die Vorlagenzeichenfolgen müssen ein$
Präfix haben (was sich etwas seltsam anfühlt - aber die Gesamtlösung ist meiner Meinung nach besser).Auf dieser Grundlage wurde ein Convenience-Wrapper gebildet:
Ebenso ein Wrapper basierend auf Svens Antwort, der die Standard-String-Formatierung verwendet:
quelle
Ich bin mir nicht sicher, ob dies als schnelle Problemumgehung in Ordnung ist, aber wie wäre es damit?
? :) :)
quelle
Wenn Sie eine eigene definieren,
Formatter
die dieget_value
Methode überschreibt , können Sie damit undefinierte Feldnamen beliebig zuordnen:http://docs.python.org/library/string.html#string.Formatter.get_value
Zum Beispiel könnten Sie zuordnen
bar
,"{bar}"
wennbar
nicht in den kwargs.Dies erfordert jedoch die Verwendung der
format()
Methode Ihres Formatter-Objekts und nicht derformat()
Methode der Zeichenfolge .quelle
Probieren Sie es aus.
quelle
{{
und}}
ist ein Weg, um den Formatierungsmarkierungen zu entkommen, führt alsoformat()
keine Ersetzung durch und ersetzt{{
bzw.}}
durch{
und}
.{{ }}
nur für ein Format funktioniert. Wenn Sie mehr anwenden müssen, müssen Sie mehr hinzufügen{}
. Ex.'fd:{uid}:{{topic_id}}'.format(uid=123).format(a=1)
gibt einen Fehler zurück, da das zweite Format dentopic_id
Wert nicht bereitstellt .Dank Bernsteins Kommentar habe ich mir Folgendes ausgedacht:
quelle
{field!s: >4}
wird, dh ( wird{field}
Für mich war das gut genug:
quelle
Alle Lösungen, die ich gefunden habe, schienen Probleme mit erweiterten Spezifikationen oder Konvertierungsoptionen zu haben. Der FormatPlaceholder von @ SvenMarnach ist wunderbar clever, funktioniert aber mit Zwang (z. B.
{a!s:>2s}
) nicht richtig, da er die__str__
Methode (in diesem Beispiel) anstelle von aufruft__format__
und Sie keine zusätzliche Formatierung verlieren.Hier ist, was ich am Ende hatte und einige seiner Hauptmerkmale:
str.format
(nicht nur ein Mapping){k!s}
{!r}
{k:>{size}}
{k.foo}
{k[0]}
{k!s:>{size}}
Ich entdeckte die Probleme mit den verschiedenen Implementierungen, nachdem ich einige Tests geschrieben hatte, wie sich diese Methode verhalten sollte. Sie sind unten, wenn jemand sie aufschlussreich findet.
quelle
Mein Vorschlag wäre der folgende (getestet mit Python3.6):
Update: Eine noch elegantere Methode (Unterklassen
dict
und Überladen__missing__(self, key)
) wird hier gezeigt: https://stackoverflow.com/a/17215533/333403quelle
Angenommen, Sie verwenden die Zeichenfolge erst, wenn sie vollständig ausgefüllt ist, können Sie Folgendes tun:
Beispiel:
quelle
Es gibt noch eine weitere Möglichkeit, dies zu erreichen, indem Variablen verwendet
format
und%
ersetzt werden. Beispielsweise:quelle
Eine sehr hässliche, aber einfachste Lösung für mich ist, einfach zu tun:
Auf diese Weise können Sie weiterhin
tmpl
als reguläre Vorlage verwenden und nur bei Bedarf eine Teilformatierung durchführen. Ich finde dieses Problem zu trivial, um eine Overkilling-Lösung wie die von Mohan Raj zu verwenden.quelle
Nachdem ich hier und da die vielversprechendsten Lösungen getestet hatte , stellte ich fest, dass keine von ihnen wirklich die folgenden Anforderungen erfüllte:
str.format_map()
der Vorlage erkannt wird .Also habe ich meine eigene Lösung geschrieben, die die oben genannten Anforderungen erfüllt. ( BEARBEITEN : Jetzt scheint die Version von @SvenMarnach - wie in dieser Antwort angegeben - die Eckfälle zu behandeln, die ich brauchte).
Grundsätzlich habe ich die Vorlagenzeichenfolge analysiert, passende verschachtelte
{.*?}
Gruppen gefunden (mithilfe einerfind_all()
Hilfsfunktion) und die formatierte Zeichenfolge schrittweise und direkt mithilfe erstellt,str.format_map()
während ich potenzielle Potenziale abfingKeyError
.(Dieser Code ist auch in FlyingCircus verfügbar - HAFTUNGSAUSSCHLUSS: Ich bin der Hauptautor davon.)
Die Verwendung für diesen Code wäre:
Vergleichen wir dies mit meiner Lieblingslösung (von @SvenMarnach, der freundlicherweise hier und da seinen Code geteilt hat ):
Hier sind einige Tests:
und den Code, um es zum Laufen zu bringen:
ergebend:
Wie Sie sehen können, scheint die aktualisierte Version jetzt die Eckfälle gut zu handhaben, in denen die frühere Version früher fehlgeschlagen ist.
Zeitlich sind sie innerhalb von rd. 50% voneinander, abhängig vom tatsächlichen
text
Format (und wahrscheinlich vom tatsächlichen Formatsource
),safe_format_map()
scheint aber bei den meisten von mir durchgeführten Tests einen Vorteil zu haben (was auch immer sie bedeuten):quelle
{d[x]}
dies meines Wissens keine gültige Formatzeichenfolge ist.field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
und beides explizitstr.format()
undstr.format_map()
verstehen es. Ich würde sagen, es gibt genügend Beweise dafür, dass dies eine gültige Formatzeichenfolge ist.str.format()
mit einem nicht ganzzahligen Index in eckigen Klammern geben? Ich kann nur ganzzahlige Indizes zum Laufen bringen.a = dict(b='YAY!'); '{a[b]}'.format_map(dict(a=a))
bringt dir "YAY!"a[b]
in Python-Code interpretiert wird , aber es ist tatsächlicha["b"]
Danke!Wenn Sie ein Wörterbuch entpacken möchten, an das Argumente übergeben werden sollen
format
, wie in dieser verwandten Frage , können Sie die folgende Methode verwenden.Nehmen Sie zunächst an, dass die Zeichenfolge
s
dieselbe ist wie in dieser Frage:und die Werte werden durch das folgende Wörterbuch angegeben:
Das wird natürlich nicht funktionieren:
Sie können jedoch zuerst eines
set
der genannten Argumente abrufens
und ein Wörterbuch erstellen, das das Argument in geschweiften Klammern auf sich selbst abbildet:Verwenden Sie nun das
args
Wörterbuch, um die fehlenden Schlüssel einzugebenreplacements
. Für Python 3.5+ können Sie dies in einem einzigen Ausdruck tun :Für ältere Versionen von Python können Sie Folgendes aufrufen
update
:quelle
Ich mag @ sven-marnach Antwort. Meine Antwort ist einfach eine erweiterte Version davon. Es ermöglicht die Formatierung ohne Schlüsselwörter und ignoriert zusätzliche Schlüssel. Hier einige Anwendungsbeispiele (der Name einer Funktion verweist auf die Formatierung von Python 3.6-F-Strings):
Und hier ist mein Code:
quelle
Wenn Sie viel Templating betreiben und feststellen, dass Pythons integrierte String-Template-Funktionalität unzureichend oder klobig ist, schauen Sie sich Jinja2 an .
Aus den Dokumenten:
quelle
Beim Lesen des Kommentars von @Sam Bourne habe ich den Code von @ SvenMarnach so geändert , dass er mit Zwang (wie
{a!s:>2s}
) ordnungsgemäß funktioniert, ohne einen benutzerdefinierten Parser zu schreiben. Die Grundidee besteht nicht darin, in Zeichenfolgen zu konvertieren, sondern fehlende Schlüssel mit Zwangs-Tags zu verketten.Verwenden Sie (zum Beispiel) so
Die folgenden Tests (inspiriert von Tests von @ norok2) überprüfen die Ausgabe für die traditionellen
format_map
und asafe_format_map
basierend auf der obigen Klasse in zwei Fällen: Bereitstellung korrekter Schlüsselwörter oder ohne diese.Welche Ausgänge
quelle
Sie können es in eine Funktion einschließen, die Standardargumente akzeptiert:
quelle