Zeichenfolgenformatierung:% vs. .format

1349

Python 2.6 führte die str.format()Methode mit einer etwas anderen Syntax als der vorhandene %Operator ein. Was ist besser und für welche Situationen?

  1. Im Folgenden wird jede Methode verwendet und das gleiche Ergebnis erzielt. Was ist also der Unterschied?

    #!/usr/bin/python
    sub1 = "python string!"
    sub2 = "an arg"
    
    a = "i am a %s" % sub1
    b = "i am a {0}".format(sub1)
    
    c = "with %(kwarg)s!" % {'kwarg':sub2}
    d = "with {kwarg}!".format(kwarg=sub2)
    
    print a    # "i am a python string!"
    print b    # "i am a python string!"
    print c    # "with an arg!"
    print d    # "with an arg!"
    
  2. Wann erfolgt die Formatierung von Zeichenfolgen in Python? Wenn beispielsweise meine Protokollierungsstufe auf HIGH eingestellt ist, kann ich trotzdem einen Treffer für die Ausführung des folgenden %Vorgangs erzielen? Und wenn ja, gibt es eine Möglichkeit, dies zu vermeiden?

    log.debug("some debug info: %s" % some_info)
NorthIsUp
quelle
2
Für Anfänger: Hier ist ein sehr schönes Tutorial , das beide Stile lehrt. Ich persönlich verwende den älteren %Stil häufiger, denn wenn Sie die verbesserten Funktionen des format()Stils nicht benötigen , ist der %Stil oft viel praktischer.
Lutz Prechelt
2
Als Referenz: Python 3-Dokumentation für den neueren format()Formatierungsstil und den älteren %Formatierungsstil .
Lutz Prechelt
1
Um Ihre zweite Frage zu beantworten, können Sie seit 3.2 das Format {} verwenden, wenn Sie einen benutzerdefinierten Formatierer verwenden (siehe docs.python.org/3/library/logging.html#logging.Formatter )
yanjost

Antworten:

953

Um Ihre erste Frage zu beantworten ... .formatscheint in vielerlei Hinsicht anspruchsvoller zu sein. Eine nervige Sache %ist auch, wie es entweder eine Variable oder ein Tupel aufnehmen kann. Sie würden denken, dass Folgendes immer funktionieren würde:

"hi there %s" % name

doch wenn es namepassiert, (1, 2, 3)wird es ein werfen TypeError. Um sicherzustellen, dass es immer gedruckt wird, müssen Sie dies tun

"hi there %s" % (name,)   # supply the single argument as a single-item tuple

Das ist einfach hässlich. .formathat diese Probleme nicht. Auch im zweiten Beispiel, das Sie gegeben haben, .formatsieht das Beispiel viel sauberer aus.

Warum würdest du es nicht benutzen?

  • Ich weiß nichts davon (ich vor dem Lesen)
  • muss mit Python 2.5 kompatibel sein

Um Ihre zweite Frage zu beantworten, erfolgt die Zeichenfolgenformatierung gleichzeitig mit jeder anderen Operation - wenn der Zeichenfolgenformatierungsausdruck ausgewertet wird. Und Python, das keine faule Sprache ist, wertet Ausdrücke aus, bevor Funktionen aufgerufen werden. In Ihrem log.debugBeispiel wird der Ausdruck also "some debug info: %s"%some_infozuerst ausgewertet, z. B. "some debug info: roflcopters are active"wird diese Zeichenfolge übergeben log.debug().

Claudiu
quelle
113
was"%(a)s, %(a)s" % {'a':'test'}
ted
128
Beachten Sie, dass Sie Zeit für, log.debug("something: %s" % x)aber nicht für verschwenden. log.debug("something: %s", x) Die Formatierung der Zeichenfolge wird in der Methode behandelt und Sie erhalten keinen Leistungseinbruch, wenn sie nicht protokolliert wird. Wie immer antizipiert Python Ihre Bedürfnisse =)
darkfeline
63
ted: das ist ein schlechter aussehender hack, um das gleiche zu tun wie '{0}, {0}'.format('test').
fliegende Schafe
19
Der Punkt ist: Das einzige wiederkehrende Argument, dass die neue Syntax die Neuordnung von Elementen ermöglicht, ist ein strittiger Punkt: Sie können dasselbe mit der alten Syntax tun. Die meisten Menschen wissen nicht, dass dies tatsächlich bereits im Ansi C99 Std! Definiert ist. Schauen Sie sich eine aktuelle Kopie von an man sprintfund erfahren Sie mehr über die $Notation in %Platzhaltern
siehe
29
@cfi: Wenn Sie so etwas wie printf("%2$d", 1, 3)"3" ausdrucken möchten , ist dies in POSIX angegeben, nicht in C99. In der Manpage, auf die Sie verwiesen haben, heißt es: "Der C99-Standard enthält den Stil nicht mit '$' ...".
Thanatos
307

Etwas, das der Modulo-Operator (%) nicht kann, afaik:

tu = (12,45,22222,103,6)
print '{0} {2} {1} {2} {3} {2} {4} {2}'.format(*tu)

Ergebnis

12 22222 45 22222 103 22222 6 22222

Sehr hilfreich.

Ein weiterer Punkt: Als format()Funktion kann sie als Argument in anderen Funktionen verwendet werden:

li = [12,45,78,784,2,69,1254,4785,984]
print map('the number is {}'.format,li)   

print

from datetime import datetime,timedelta

once_upon_a_time = datetime(2010, 7, 1, 12, 0, 0)
delta = timedelta(days=13, hours=8,  minutes=20)

gen =(once_upon_a_time +x*delta for x in xrange(20))

print '\n'.join(map('{:%Y-%m-%d %H:%M:%S}'.format, gen))

Ergebnisse in:

['the number is 12', 'the number is 45', 'the number is 78', 'the number is 784', 'the number is 2', 'the number is 69', 'the number is 1254', 'the number is 4785', 'the number is 984']

2010-07-01 12:00:00
2010-07-14 20:20:00
2010-07-28 04:40:00
2010-08-10 13:00:00
2010-08-23 21:20:00
2010-09-06 05:40:00
2010-09-19 14:00:00
2010-10-02 22:20:00
2010-10-16 06:40:00
2010-10-29 15:00:00
2010-11-11 23:20:00
2010-11-25 07:40:00
2010-12-08 16:00:00
2010-12-22 00:20:00
2011-01-04 08:40:00
2011-01-17 17:00:00
2011-01-31 01:20:00
2011-02-13 09:40:00
2011-02-26 18:00:00
2011-03-12 02:20:00
eyquem
quelle
17
Sie können die Formatierung im alten Stil mapgenauso einfach wie das Formatieren verwenden. map('some_format_string_%s'.__mod__, some_iterable)
Agf
3
@cfi: Bitte beweisen Sie, dass Sie Recht haben, indem Sie das obige Beispiel in C99
MarcH
9
@MarcH: printf("%2$s %1$s\n", "One", "Two");kompiliert mit gcc -std=c99 test.c -o test, die Ausgabe ist Two One. Aber ich stehe korrigiert da: Es ist eigentlich eine POSIX-Erweiterung und nicht C. Ich kann sie im C / C ++ - Standard nicht wiederfinden, wo ich dachte, ich hätte sie gesehen. Der Code funktioniert sogar mit dem Standardflag 'c90'. sprintfManpage . Dies listet es nicht auf, ermöglicht es libs jedoch, eine Obermenge zu implementieren. Mein ursprüngliches Argument ist immer noch gültig und ersetzt CdurchPosix
cfi
8
Mein erster Kommentar hier gilt nicht für diese Antwort. Ich bedauere die Formulierung. In Python können wir den Modulo-Operator nicht %zum Neuordnen von Platzhaltern verwenden. Ich möchte diesen ersten Kommentar aus Gründen der Kommentarkonsistenz hier immer noch nicht löschen. Ich entschuldige mich dafür, dass ich meine Wut hier abgelegt habe. Es richtet sich gegen die oft gemachte Aussage, dass die alte Syntax per se dies nicht zulassen würde. Anstatt eine völlig neue Syntax zu erstellen, hätten wir die Standard-Posix-Erweiterungen einführen können. Wir könnten beides haben.
cfi
17
'modulo' bezieht sich auf den Operator, der einen Rest nach einer Division auswertet. In diesem Fall ist das Prozentzeichen kein Modulo-Operator.
Octopus
148

Angenommen, Sie verwenden das Python- loggingModul, können Sie die Argumente für die Zeichenfolgenformatierung als Argumente an die .debug()Methode übergeben, anstatt die Formatierung selbst vorzunehmen:

log.debug("some debug info: %s", some_info)

Dadurch wird die Formatierung vermieden, es sei denn, der Logger protokolliert tatsächlich etwas.

Wooble
quelle
10
Dies sind einige nützliche Informationen, die ich gerade gelernt habe. Schade, dass es keine eigene Frage gibt, da es von der Hauptfrage getrennt zu sein scheint. Schade, dass der OP seine Frage nicht in zwei separate Fragen aufgeteilt hat.
14.
12
Sie können die Diktatformatierung wie folgt verwenden: log.debug("some debug info: %(this)s and %(that)s", dict(this='Tom', that='Jerry')) Sie können hier jedoch nicht die neue .format()Stilsyntax verwenden, auch nicht in Python 3.3, was eine Schande ist.
Cito
15
@Cito: Siehe dies: plumberjack.blogspot.co.uk/2010/10/…
Vinay Sajip
26
Der Hauptvorteil davon ist nicht die Leistung (die String-Interpolation ist im Vergleich zu allem, was Sie mit der Ausgabe der Protokollierung tun, z. B. Anzeigen in einem Terminal, Speichern auf der Festplatte), schnell. Wenn Sie einen Protokollierungsaggregator haben, ist dies der Fall kann Ihnen sagen, dass "Sie 12 Instanzen dieser Fehlermeldung erhalten haben", auch wenn alle unterschiedliche 'some_info'-Werte hatten. Wenn die Formatierung der Zeichenfolge erfolgt, bevor die Zeichenfolge an log.debug übergeben wird, ist dies nicht möglich. Der Aggregator kann nur sagen "Sie hatten 12 verschiedene Protokollnachrichten"
Jonathan Hartley
7
Wenn Sie sich Gedanken über die Leistung machen, verwenden Sie die wörtliche dict {} -Syntax
trojjer
119

Ab Python 3.6 (2016) können Sie Variablen durch f-Strings ersetzen:

>>> origin = "London"
>>> destination = "Paris"
>>> f"from {origin} to {destination}"
'from London to Paris'

Beachten Sie das f"Präfix. Wenn Sie dies in Python 3.5 oder früher versuchen, erhalten Sie eine SyntaxError.

Siehe https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings

Oberst Panik
quelle
1
Dies beantwortet die Frage nicht. Eine andere Antwort, in der F-Strings erwähnt werden, spricht zumindest von Leistung: stackoverflow.com/a/51167833/7851470
Georgy
60

PEP 3101 schlägt vor, den %Operator durch die neue, erweiterte Zeichenfolgenformatierung in Python 3 zu ersetzen , wo dies die Standardeinstellung wäre.

BrainStorm
quelle
14
Unwahr: "Die Abwärtskompatibilität kann aufrechterhalten werden, indem die vorhandenen Mechanismen beibehalten werden."; Ersetzt natürlich .formatnicht die % Formatierung von Zeichenfolgen.
Tobias
12
Nein, die Postulation von BrainStorms ist wahr: "als Ersatz für das vorhandene '%' gedacht". Tobias Zitat bedeutet, dass beide Systeme für einige Zeit koexistieren werden. RTFPEP
Phobie
54

Aber bitte seien Sie vorsichtig, gerade habe ich ein Problem entdeckt, als ich versuchte, alle %durch .formatvorhandenen Code zu ersetzen : '{}'.format(unicode_string)Ich werde versuchen, unicode_string zu codieren, und es wird wahrscheinlich fehlschlagen.

Schauen Sie sich einfach dieses interaktive Python-Sitzungsprotokoll an:

Python 2.7.2 (default, Aug 27 2012, 19:52:55) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
; s='й'
; u=u'й'
; s
'\xd0\xb9'
; u
u'\u0439'

sist nur eine Zeichenfolge (in Python3 als "Byte-Array" bezeichnet) und ueine Unicode-Zeichenfolge (in Python3 als "Zeichenfolge" bezeichnet):

; '%s' % s
'\xd0\xb9'
; '%s' % u
u'\u0439'

Wenn Sie dem %Operator ein Unicode-Objekt als Parameter geben, wird eine Unicode-Zeichenfolge erzeugt, auch wenn die ursprüngliche Zeichenfolge nicht Unicode war:

; '{}'.format(s)
'\xd0\xb9'
; '{}'.format(u)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u0439' in position 0: ordinal not in range(256)

Die .formatFunktion löst jedoch "UnicodeEncodeError" aus:

; u'{}'.format(s)
u'\xd0\xb9'
; u'{}'.format(u)
u'\u0439'

und es funktioniert nur dann mit einem Unicode-Argument, wenn die ursprüngliche Zeichenfolge Unicode war.

; '{}'.format(u'i')
'i'

oder wenn die Argumentzeichenfolge in eine Zeichenfolge konvertiert werden kann (sogenanntes 'Byte-Array')

Wobmene
quelle
12
Es gibt einfach keinen Grund, den Arbeitscode zu ändern, es sei denn, die zusätzlichen Funktionen der neuen formatMethode werden wirklich benötigt ...
Tobias
stimme dir absolut zu, Tobias, aber manchmal wird es benötigt, wenn ein Upgrade auf neuere Versionen von Python durchgeführt wird
Wobmene
2
Zum Beispiel? AFAIK, es wurde nie gebraucht; Ich halte es nicht für wahrscheinlich, dass die %String-Interpolation jemals verschwinden würde.
Tobias
4
Ich halte .format () für sicherer als% für Strings. Oft sehe ich Anfängerfehler wie diesen "p1=%s p2=%d" % "abc", 2oder "p1=%s p2=%s" % (tuple_p1_p2,). Sie könnten denken, es ist die Schuld des Codierers, aber ich denke, es ist nur eine seltsame fehlerhafte Syntax, die für das Quicky-Scriptie gut aussieht, aber für den Produktionscode schlecht ist.
Wobmene
3
Aber ich mag die Syntax von .format () nicht, ich wäre glücklicher mit guten alten %s, %02dwie "p1=%s p2=%02d".format("abc", 2). Ich beschuldige diejenigen, die die Formatierung der geschweiften Klammern erfunden und genehmigt haben, die Sie brauchen, um ihnen zu entkommen, {{}}und die imho hässlich aussehen.
Wobmene
35

Ein weiterer Vorteil von .format(den ich in den Antworten nicht sehe): Es kann Objekteigenschaften annehmen.

In [12]: class A(object):
   ....:     def __init__(self, x, y):
   ....:         self.x = x
   ....:         self.y = y
   ....:         

In [13]: a = A(2,3)

In [14]: 'x is {0.x}, y is {0.y}'.format(a)
Out[14]: 'x is 2, y is 3'

Oder als Schlüsselwortargument:

In [15]: 'x is {a.x}, y is {a.y}'.format(a=a)
Out[15]: 'x is 2, y is 3'

%Soweit ich das beurteilen kann, ist dies nicht möglich .

matiasg
quelle
4
Dies sieht im Vergleich zum Äquivalent unleserlicher als nötig aus 'x is {0}, y is {1}'.format(a.x, a.y). Sollte nur verwendet werden, wenn die a.xOperation sehr kostspielig ist.
Thetheor
13
@dtheodor Mit einem zwicken ein Schlüsselwort - Argument zu verwenden , anstatt Positions Argument ... 'x is {a.x}, y is {a.y}'.format(a=a). Lesbarer als beide Beispiele.
CivFan
1
@CivFan Oder, wenn Sie mehr als ein Objekt haben,'x is {a.x}, y is {a.y}'.format(**vars())
Jack
1
Beachten Sie auch diesen auf die gleiche Weise : '{foo[bar]}'.format(foo={'bar': 'baz'}).
Antoine Pinsard
3
Dies ist unglaublich nützlich für kundenorientierte Anwendungen, bei denen Ihre Anwendung einen Standardsatz von Formatierungsoptionen mit einer vom Benutzer angegebenen Formatzeichenfolge bereitstellt. Ich benutze das die ganze Zeit. Die Konfigurationsdatei verfügt beispielsweise über eine "messagestring" -Eigenschaft, die der Benutzer bereitstellen kann Your order, number {order[number]} was processed at {now:%Y-%m-%d %H:%M:%S}, will be ready at about {order[eta]:%H:%M:%S}oder was auch immer er möchte. Dies ist weitaus sauberer als der Versuch, die gleiche Funktionalität wie der alte Formatierer anzubieten. Es macht vom Benutzer bereitgestellte Formatzeichenfolgen viel leistungsfähiger.
Taywee
35

%gibt bessere Leistung als formataus meinem Test.

Testcode:

Python 2.7.2:

import timeit
print 'format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')")
print '%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')")

Ergebnis:

> format: 0.470329046249
> %: 0.357107877731

Python 3.5.2

import timeit
print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))

Ergebnis

> format: 0.5864730989560485
> %: 0.013593495357781649

Es sieht in Python2 so aus, der Unterschied ist gering, während es in Python3 %viel schneller ist als format.

Vielen Dank an Chris Cogdon für den Beispielcode.

Bearbeiten 1:

Im Juli 2019 erneut in Python 3.7.2 getestet.

Ergebnis:

> format: 0.86600608
> %: 0.630180146

Es gibt keinen großen Unterschied. Ich denke, Python verbessert sich allmählich.

Bearbeiten 2:

Nachdem jemand den F-String von Python 3 im Kommentar erwähnt hatte, führte ich unter Python 3.7.2 einen Test für den folgenden Code durch:

import timeit
print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))
print('f-string:', timeit.timeit("f'{1}{1.23}{\"hello\"}'"))

Ergebnis:

format: 0.8331376779999999
%: 0.6314778750000001
f-string: 0.766649943

Es scheint, dass F-String immer noch langsamer als, %aber besser als ist format.

lcltj
quelle
42
Bietet stattdessen str.formatmehr Funktionen (insbesondere typspezifische Formatierung, z '{0:%Y-%m-%d}'.format(datetime.datetime.utcnow()). B. ). Leistung kann nicht die absolute Voraussetzung für alle Jobs sein. Verwenden Sie das richtige Werkzeug für den Job.
Minhee
36
"Vorzeitige Optimierung ist die Wurzel allen Übels", sagte Donald Knuth einmal ...
Yatharth Agarwal
22
Das Festhalten an einem bekannten Formatierungsschema (sofern es den Anforderungen entspricht, was in den allermeisten Fällen der Fall ist) und das doppelt so schnell ist, ist keine "vorzeitige Optimierung", sondern einfach sinnvoll. Übrigens %erlaubt der Bediener, printfWissen wiederzuverwenden ; Die Wörterbuchinterpolation ist eine sehr einfache Erweiterung des Prinzips.
Tobias
5
Ich habe tatsächlich das Gegenteil in einer Situation erlebt. Die Formatierung im neuen Stil war schneller. Können Sie den von Ihnen verwendeten Testcode angeben?
David Sanders
8
Scheint ein ernsthaft verschwendeter Beitrag ohne Beispiele oder Argumente zu sein, behauptet nur.
Kevr
31

Wie ich heute entdecken, über die alte Art und Weise Saiten der Formatierung %nicht unterstützt Decimal, Python - Modul für dezimal festen Punkt und Gleitkomma - Arithmetik, aus dem Kasten heraus .

Beispiel (mit Python 3.3.5):

#!/usr/bin/env python3

from decimal import *

getcontext().prec = 50
d = Decimal('3.12375239e-24') # no magic number, I rather produced it by banging my head on my keyboard

print('%.50f' % d)
print('{0:.50f}'.format(d))

Ausgabe:

0,00000000000000000000000312375239000000009907464850 0,00000000000000000000000312375239000000000000000000

Möglicherweise gibt es Workarounds, aber Sie können die format()Methode trotzdem sofort anwenden .

balu
quelle
1
Dies liegt wahrscheinlich daran, dass Formatierungen im neuen Stil str(d)vor dem Erweitern des Parameters aufgerufen werden, während Formatierungen im alten Stil wahrscheinlich float(d)zuerst aufgerufen werden .
David Sanders
3
Sie würden so denken, aber str(d)kehrt zurück "3.12375239e-24", nicht"0.00000000000000000000000312375239000000000000000000"
Jack
18

Wenn Ihr Python> = 3.6 ist, ist das F-String-formatierte Literal Ihr neuer Freund.

Es ist einfacher, sauberer und leistungsfähiger.

In [1]: params=['Hello', 'adam', 42]

In [2]: %timeit "%s %s, the answer to everything is %d."%(params[0],params[1],params[2])
448 ns ± 1.48 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [3]: %timeit "{} {}, the answer to everything is {}.".format(*params)
449 ns ± 1.42 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit f"{params[0]} {params[1]}, the answer to everything is {params[2]}."
12.7 ns ± 0.0129 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
Zhengcao
quelle
15

Nebenbei bemerkt, Sie müssen keinen Leistungseinbruch hinnehmen, um die Formatierung im neuen Stil für die Protokollierung zu verwenden. Sie können eine beliebiges Objekt zu übergeben logging.debug, logging.infousw. , dass Geräte der __str__magischen Methode. Wenn das Protokollierungsmodul entschieden hat, dass es Ihr Nachrichtenobjekt (was auch immer es sein soll) ausgeben muss, ruft es str(message_object)vorher auf. Sie könnten also so etwas tun:

import logging


class NewStyleLogMessage(object):
    def __init__(self, message, *args, **kwargs):
        self.message = message
        self.args = args
        self.kwargs = kwargs

    def __str__(self):
        args = (i() if callable(i) else i for i in self.args)
        kwargs = dict((k, v() if callable(v) else v) for k, v in self.kwargs.items())

        return self.message.format(*args, **kwargs)

N = NewStyleLogMessage

# Neither one of these messages are formatted (or calculated) until they're
# needed

# Emits "Lazily formatted log entry: 123 foo" in log
logging.debug(N('Lazily formatted log entry: {0} {keyword}', 123, keyword='foo'))


def expensive_func():
    # Do something that takes a long time...
    return 'foo'

# Emits "Expensive log entry: foo" in log
logging.debug(N('Expensive log entry: {keyword}', keyword=expensive_func))

Dies alles wird in der Python 3-Dokumentation beschrieben ( https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles ). Es funktioniert jedoch auch mit Python 2.6 ( https://docs.python.org/2.6/library/logging.html#using-arbitrary-objects-as-messages ).

Einer der Vorteile dieser Technik, abgesehen von der Tatsache, dass sie im Formatierungsstil agnostisch ist, besteht darin, dass sie verzögerte Werte zulässt, z. B. die expensive_funcobige Funktion . Dies bietet eine elegantere Alternative zu den Ratschlägen in den Python-Dokumenten hier: https://docs.python.org/2.6/library/logging.html#optimization .

David Sanders
quelle
2
Ich wünschte, ich könnte dies mehr unterstützen. Es ermöglicht die Protokollierung mit formatohne Leistungseinbußen - dies geschieht durch genaues Überschreiben __str__wie vorgesehen logging- verkürzt den Funktionsaufruf auf einen einzelnen Buchstaben ( N), der sich einigen der Standardmethoden zum Definieren von Zeichenfolgen sehr ähnlich anfühlt - UND ermöglicht Faulheit Funktionsaufruf. Vielen Dank! +1
CivFan
2
Unterscheidet sich das Ergebnis von der Verwendung des logging.Formatter(style='{')Parameters?
DavidA
10

Eine Situation, in der dies %hilfreich sein kann, ist das Formatieren von Regex-Ausdrücken. Zum Beispiel,

'{type_names} [a-z]{2}'.format(type_names='triangle|square')

erhöht IndexError. In dieser Situation können Sie Folgendes verwenden:

'%(type_names)s [a-z]{2}' % {'type_names': 'triangle|square'}

Dadurch wird vermieden, dass der reguläre Ausdruck als geschrieben wird '{type_names} [a-z]{{2}}'. Dies kann nützlich sein, wenn Sie zwei reguläre Ausdrücke haben, von denen einer allein ohne Format verwendet wird, die Verkettung beider jedoch formatiert ist.

Jorge Leitao
quelle
3
Oder einfach benutzen '{type_names} [a-z]{{2}}'.format(type_names='triangle|square'). Es ist wie zu sagen, .format()kann helfen, wenn Zeichenfolgen verwendet werden, die bereits ein Prozentzeichen enthalten. Sicher. Dann musst du ihnen entkommen.
Alfe
1
@Alfe Sie haben Recht, und deshalb beginnt die Antwort mit "One situation where % may help is when you are formatting regex expressions."Insbesondere wird angenommen, dass a=r"[a-z]{2}"es sich um einen Regex-Block handelt, der in zwei verschiedenen Endausdrücken (z . B. c1 = b + aund c2 = a) verwendet wird. Angenommen, dies c1muss bearbeitet werden format(z. B. bmuss die Laufzeit formatiert werden), aber c2nicht. Dann brauchen Sie a=r"[a-z]{2}"für c2und a=r"[a-z]{{2}}"für c1.format(...).
Jorge Leitao
7

Ich würde hinzufügen, dass wir seit Version 3.6 fstrings wie die folgenden verwenden können

foo = "john"
bar = "smith"
print(f"My name is {foo} {bar}")

Welche geben

Ich heiße John Smith

Alles wird in Strings umgewandelt

mylist = ["foo", "bar"]
print(f"mylist = {mylist}")

Ergebnis:

mylist = ['foo', 'bar']

Sie können die Funktion wie in anderen Formaten übergeben

print(f'Hello, here is the date : {time.strftime("%d/%m/%Y")}')

Zum Beispiel geben

Hallo, hier ist das Datum: 16/04/2018

Sylvan LE DEUNFF
quelle
4

Für Python-Version> = 3.6 (siehe PEP 498 )

s1='albha'
s2='beta'

f'{s1}{s2:>10}'

#output
'albha      beta'
Roushan
quelle
2

Python 3.6.7 vergleichend:

#!/usr/bin/env python
import timeit

def time_it(fn):
    """
    Measure time of execution of a function
    """
    def wrapper(*args, **kwargs):
        t0 = timeit.default_timer()
        fn(*args, **kwargs)
        t1 = timeit.default_timer()
        print("{0:.10f} seconds".format(t1 - t0))
    return wrapper


@time_it
def new_new_format(s):
    print("new_new_format:", f"{s[0]} {s[1]} {s[2]} {s[3]} {s[4]}")


@time_it
def new_format(s):
    print("new_format:", "{0} {1} {2} {3} {4}".format(*s))


@time_it
def old_format(s):
    print("old_format:", "%s %s %s %s %s" % s)


def main():
    samples = (("uno", "dos", "tres", "cuatro", "cinco"), (1,2,3,4,5), (1.1, 2.1, 3.1, 4.1, 5.1), ("uno", 2, 3.14, "cuatro", 5.5),) 
    for s in samples:
        new_new_format(s)
        new_format(s)
        old_format(s)
        print("-----")


if __name__ == '__main__':
    main()

Ausgabe:

new_new_format: uno dos tres cuatro cinco
0.0000170280 seconds
new_format: uno dos tres cuatro cinco
0.0000046750 seconds
old_format: uno dos tres cuatro cinco
0.0000034820 seconds
-----
new_new_format: 1 2 3 4 5
0.0000043980 seconds
new_format: 1 2 3 4 5
0.0000062590 seconds
old_format: 1 2 3 4 5
0.0000041730 seconds
-----
new_new_format: 1.1 2.1 3.1 4.1 5.1
0.0000092650 seconds
new_format: 1.1 2.1 3.1 4.1 5.1
0.0000055340 seconds
old_format: 1.1 2.1 3.1 4.1 5.1
0.0000052130 seconds
-----
new_new_format: uno 2 3.14 cuatro 5.5
0.0000053380 seconds
new_format: uno 2 3.14 cuatro 5.5
0.0000047570 seconds
old_format: uno 2 3.14 cuatro 5.5
0.0000045320 seconds
-----
Felix Martinez
quelle
3
Sie sollten jedes Beispiel mehrmals ausführen. Ein einzelner Lauf kann irreführend sein, z. B. ist das Betriebssystem im Allgemeinen ausgelastet, sodass die Ausführung Ihres Codes verzögert wird. Weitere Informationen finden Sie in den Dokumenten: docs.python.org/3/library/timeit.html . (schöner Avatar, Guybrush!)
jake77
1

Aber eine Sache ist, dass auch wenn Sie geschweifte geschweifte Klammern haben, nicht für das Format funktioniert, sondern %funktioniert.

Beispiel:

>>> '{{0}, {1}}'.format(1,2)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    '{{0}, {1}}'.format(1,2)
ValueError: Single '}' encountered in format string
>>> '{%s, %s}'%(1,2)
'{1, 2}'
>>> 
U10-Vorwärts
quelle
2
Sie könnten dies tun, aber ich stimme zu, dass es ein beeindruckendes '{{{0}, {1}}}' Format (1, 2) ist
Sylvan LE DEUNFF
Geschachtelte geschweifte Klammern funktionieren und sind hübsch.
CivFan