33. String-Formatierung¶
Suchst du nach einer einfachen Möglichkeit, Variablen für die Anzeige zu formatieren und mit anderem Text zu mischen? Fügst du einer großen Zahl Tausender-Trennzeichen (Kommas in den USA) hinzu und formatierst Dezimalstellen nach deinen Wünschen? Du benötigst „String-Formatierung“.
Python bietet drei Möglichkeiten zum Formatieren von Zeichenfolgen. Die alte Methode (old string formatting), die ursprünglich aus der Formatierung älterer Sprachen wie C stammt. Der neuere Weg, der in Python 3 eingeführt wurde, sollte besser sein, war es aber wohl nicht. Und der neue Weg, der in Python 3.6 mit PEP-498 eingeführt wurde. Wir werden den neuesten Weg abdecken.
33.1. Kurzübersicht¶
Hier ist eine kurze Tabelle als Referenz für die Textformatierung. Lese weiter, um eine detaillierte Erläuterung der Funktionsweise der Textformatierung zu erhalten.
Nummer |
Format |
Ausgabe |
Beschreibung |
---|---|---|---|
|
|
|
2 Nachkommastellen |
|
|
|
2 Nachkommastellen mit Vorzeichen |
|
|
|
2 Nachkommastellen mit Vorzeichen |
|
|
|
Keine Nachkommastellen (werden gerundet) |
|
|
|
mit Nullen auf der linken Seite auffüllen |
|
|
|
Zahlenformat mit Komma als Trennzeichen |
|
|
|
Prozent |
|
|
|
Exponenten-Notation |
|
|
|
Rechtsbündig |
|
|
|
Linksbündig |
|
|
|
Zentriert |
33.2. Dezimalzahlen¶
Führe das folgende Programm aus, das mehrere Zufallszahlen ausgibt.
1 2 3 4 5 | import random
for i in range(10):
x = random.randrange(120)
print("My number: ", x)
|
Die Ausgabe ist linksbündig und die Zahlen sehen schrecklich aus:
My number: 30
My number: 2
My number: 101
My number: 3
My number: 44
My number: 111
My number: 100
My number: 48
My number: 27
My number: 92
Wir können die String-Formatierung verwenden, um die Liste der Zahlen besser aussehen zu lassen, indem wir sie rechtsbündig ausrichten. Der erste Schritt besteht darin, die „Literal String Interpolation“ für die Zeichenfolge zu verwenden. Siehe unten:
import random
for i in range(10):
x = random.randrange(120)
print(f"My number: {x}")
Dies bringt unser Programm näher an die richtige Ausrichtung der Zahl, aber wir sind noch nicht ganz da. Siehst du, wie die Zeichenfolge mit f
beginnt?
Die Zeichenfolge gibt die geschweiften Klammern {}
nicht aus, sondern ersetzt sie durch den Wert in x
. Die Ausgabe (unten) sieht genauso aus wie zuvor.
My number: 23
My number: 92
My number: 102
My number: 19
My number: 85
My number: 114
My number: 37
My number: 101
My number: 35
My number: 18
Zum rechtsbündigen Ausrichten fügen wir den geschweiften Klammern {}
weitere Informationen zum Formatieren der Zahl hinzu:
1 2 3 4 5 | import random
for i in range(10):
x = random.randrange(120)
print(f"My number: {x:3}")
|
My number: 37
My number: 108
My number: 117
My number: 55
My number: 19
My number: 97
My number: 78
My number: 12
My number: 29
My number: 0
Das ist besser. Wir haben die richtigen Zahlen! Aber wie funktioniert das? Das von uns hinzugefügte :3
ist nicht ganz intuitiv. Sieht so aus, als hätten wir gerade ein zufälliges Emoji hinzugefügt.
Hier ist die Aufteilung: Das { }
teilt dem Computer mit, dass wir eine Zahl formatieren werden. Darin schreiben wir die Variable, die wir formatieren wollen, x
in diesem Fall. Nach der Variablen setzen wir ein :
, um dem Rechner mitzuteilen, dass wir ihm Formatierungsinformationen geben werden.
In diesem Fall geben wir eine 3 an, um eine Feldbreite von drei Zeichen anzugeben. Der Feldbreitenwert weist den Computer an, zu versuchen, die Nummer in ein drei Zeichen breites Feld einzugeben. Standardmäßig wird versucht, Zahlen rechtsbündig und Text linksbündig auszurichten.
Noch besser ist, dass das Programm nicht länger str()
aufrufen muss, um die Zahl in einen String umzuwandeln! Lasse die String-Konvertierungen weg.
Was wäre, wenn wir große Zahlen hätten? Machen wir größere Zufallszahlen:
1 2 3 4 5 | import random
for i in range(10):
x = random.randrange(100000)
print(f"My number: {x:6}")
|
Dies ergibt eine Ausgabe, die richtig ausgerichtet ist, aber immer noch nicht gut aussieht.
My number: 89807
My number: 5177
My number: 24067
My number: 19887
My number: 54155
My number: 49288
My number: 31412
My number: 49633
My number: 43406
My number: 37398
Wo sind die Trennzeichen? Diese Liste würde mit Trennzeichen zwischen jeweils drei Ziffern besser aussehen. Schau dir das nächste Beispiel an, um zu sehen, wie sie hinzugefügt werden:
1 2 3 4 5 | import random
for i in range(10):
x = random.randrange(100000)
print(f"My number: {x:6,}")
|
Die Ausgabe:
My number: 86,631
My number: 57,165
My number: 19,835
My number: 22,560
My number: 43,161
My number: 16,604
My number: 20,544
My number: 33,906
My number: 89,846
My number: 27,350
Wir haben nach dem Feldbreitenbezeichner ein Komma eingefügt, und jetzt haben unsere Zahlen Kommas. Das Komma muss nach dem Feldbreitenbezeichner stehen, nicht davor. Kommas werden bei der Berechnung der Feldbreite berücksichtigt. Beispielsweise hat 1,024 eine Feldbreite von 5 und nicht von 4.
Wir können mehrere Werte ausgeben und die Werte mit Text kombinieren. Führe den folgenden Code aus.
1 2 3 4 | x = 5
y = 66
z = 777
print(f"A - '{x}' B - '{y}' C - '{z}'")
|
Das Programm ersetzt die geschweiften Klammern durch Zahlen und gibt den gesamten anderen Text in der Zeichenfolge aus:
A - '5' B - '66' C - '777'
33.3. Strings¶
Schauen wir uns an, wie Zeichenfolgen formatiert werden.
Die folgende Liste sieht schrecklich aus.
1 2 3 4 5 | my_fruit = ["Apples","Oranges","Grapes","Pears"]
my_calories = [4, 300, 70, 30]
for i in range(4):
print(my_fruit[i], "are", my_calories[i], "calories.")
|
Die Ausgabe:
Apples are 4 calories.
Oranges are 300 calories.
Grapes are 70 calories.
Pears are 30 calories.
Versuche es jetzt mit der format
-Anweisung. Beachte, wie du zusätzlichen Text und mehr als einen Wert in dieselbe Zeile einfügen kannst.
1 2 3 4 5 | my_fruit = ["Apples", "Oranges", "Grapes", "Pears"]
my_calories = [4, 300, 70, 30]
for i in range(4):
print(f"{my_fruit[i]:7} are {my_calories[i]:3} calories.")
|
Apples are 4 calories.
Oranges are 300 calories.
Grapes are 70 calories.
Pears are 30 calories.
Das ist ziemlich cool und sieht so aus, wie wir es wollen. Was aber, wenn wir nicht wollten, dass die Zahlen rechts und der Text links ausgerichtet sind? Wir können die Zeichen <
und >
wie im folgenden Beispiel verwenden:
1 2 3 4 5 | my_fruit = ["Apples", "Oranges", "Grapes", "Pears"]
my_calories = [4, 300, 70, 30]
for i in range(4):
print(f"{my_fruit[i]:>7} are {my_calories[i]:<3} calories.")
|
Apples are 4 calories.
Oranges are 300 calories.
Grapes are 70 calories.
Pears are 30 calories.
33.4. Clock Example with Leading Zeros¶
Dies erzeugt eine Ausgabe, die nicht richtig ist:
1 2 3 | for hours in range(1,13):
for minutes in range(0,60):
print(f"Time {hours}:{minutes}")
|
Time 8:56
Time 8:57
Time 8:58
Time 8:59
Time 9:0
Time 9:1
Time 9:2
Wir müssen führende Nullen verwenden, um Zahlen in Uhren anzuzeigen. Anstatt eine 2 für die Feldbreite anzugeben, verwenden Sie stattdessen 02. Dadurch wird das Feld mit Nullen und nicht mit Leerzeichen aufgefüllt.
1 2 3 | for hours in range(1, 13):
for minutes in range(0, 60):
print(f"Time {hours:02}:{minutes:02}")
|
Time 08:56
Time 08:57
Time 08:58
Time 08:59
Time 09:00
Time 09:01
Time 09:02
33.5. Gleitkommazahlen¶
Wir können auch die Ausgabe von Gleitkommazahlen steuern. Untersuche den folgenden Code und seine Ausgabe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | x = 0.1
y = 123.456789
print(f"{x:.1} {y:.1}")
print(f"{x:.2} {y:.2}")
print(f"{x:.3} {y:.3}")
print(f"{x:.4} {y:.4}")
print(f"{x:.5} {y:.5}")
print(f"{x:.6} {y:.6}")
print()
print(f"{x:.1f} {y:.1f}")
print(f"{x:.2f} {y:.2f}")
print(f"{x:.3f} {y:.3f}")
print(f"{x:.4f} {y:.4f}")
print(f"{x:.5f} {y:.5f}")
print(f"{x:.6f} {y:.6f}")
|
1 2 3 4 5 6 7 8 9 10 11 12 13 | 0.1 1e+02
0.1 1.2e+02
0.1 1.23e+02
0.1 123.5
0.1 123.46
0.1 123.457
0.1 123.5
0.10 123.46
0.100 123.457
0.1000 123.4568
0.10000 123.45679
0.100000 123.456789
|
Ein Format von .2
bedeutet, dass die Zahl mit einer Genauigkeit von zwei Ziffern angezeigt wird. Leider bedeutet dies, wenn wir die Zahl 123
anzeigen, die drei signifikante Ziffern hat, erhalten wir die Zahl in wissenschaftlicher Notation 1.2e+02
anstatt gerundet.
Ein Format von .2f
(beachte das f
) bedeutet, dass die Zahl mit zwei Nachkommastellen angezeigt wird. Die Zahl 1 würde also als 1.00
und die Zahl 1.5555
als 1.56
angezeigt.
Ein Programm kann auch die Feldbreite angeben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | x = 0.1
y = 123.456789
print(f"My number: '{x:10.1}' and '{y:10.1}'")
print(f"My number: '{x:10.2}' and '{y:10.2}'")
print(f"My number: '{x:10.3}' and '{y:10.3}'")
print(f"My number: '{x:10.4}' and '{y:10.4}'")
print(f"My number: '{x:10.5}' and '{y:10.5}'")
print(f"My number: '{x:10.6}' and '{y:10.6}'")
print()
print(f"My number: '{x:10.1f}' and '{y:10.1f}'")
print(f"My number: '{x:10.2f}' and '{y:10.2f}'")
print(f"My number: '{x:10.3f}' and '{y:10.3f}'")
print(f"My number: '{x:10.4f}' and '{y:10.4f}'")
print(f"My number: '{x:10.5f}' and '{y:10.5f}'")
print(f"My number: '{x:10.6f}' and '{y:10.6f}'")
|
Das Format 10.2f
bedeutet nicht 10 Stellen und zwei Stellen nach dem Komma. Es bedeutet eine Gesamtfeldbreite von 10. Es gibt also 7 Stellen vor der Dezimalstelle, die Dezimalstelle, die als eine weitere Stelle zählt, und 2 Stellen danach.
My number: ' 0.1' and ' 1e+02'
My number: ' 0.1' and ' 1.2e+02'
My number: ' 0.1' and ' 1.23e+02'
My number: ' 0.1' and ' 123.5'
My number: ' 0.1' and ' 123.46'
My number: ' 0.1' and ' 123.457'
My number: ' 0.1' and ' 123.5'
My number: ' 0.10' and ' 123.46'
My number: ' 0.100' and ' 123.457'
My number: ' 0.1000' and ' 123.4568'
My number: ' 0.10000' and ' 123.45679'
My number: ' 0.100000' and '123.456789'
33.6. Ausgabe von Dollar und Cent¶
Wenn du eine Gleitkommazahl für die Kosten ausgeben möchtest, verwende ein f. Siehe unten:
1 2 3 4 5 6 7 8 | cost1 = 3.07
tax1 = cost1 * 0.06
total1 = cost1 + tax1
print(f"Cost: ${cost1:5.2f}")
print(f"Tax: {tax1:5.2f}")
print(f"-------------")
print(f"Total: ${total1:5.2f}")
|
Merke! Man könnte leicht vermuten, dass %5.2f
fünf Ziffern vor dem Punkt, den Punkt, gefolgt von zwei Stellen bedeutet. Aber das tut es nicht. Dies bedeutet eine Gesamtfeldbreite von fünf, einschließlich des Punkts und der zwei Nachkommastellen. Hier ist die Ausgabe:
Cost: $ 3.07
Tax: 0.18
-------------
Total: $ 3.25
Achtung! Der obige Code weist einen Fehler auf, der bei der Arbeit mit Finanztransaktionen häufig vorkommt. Findest du ihn? Versuche es mit dem folgenden erweiterten Codebeispiel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | cost1 = 3.07
tax1 = cost1 * 0.06
total1 = cost1 + tax1
print(f"Cost: ${cost1:5.2f}")
print(f"Tax: {tax1:5.2f}")
print(f"-------------")
print(f"Total: ${total1:5.2f}")
cost2 = 5.07
tax2 = cost2 * 0.06
total2 = cost2 + tax2
print()
print(f"Cost: ${cost2:5.2f}")
print(f"Tax: {tax2:5.2f}")
print(f"-------------")
print(f"Total: ${total2:5.2f}")
print()
grand_total = total1 + total2
print(f"Grand total: ${grand_total:5.2f}")
|
Cost: $ 3.07
Tax: 0.18
------------
Total: $ 3.25
Cost: $ 5.07
Tax: 0.30
-------------
Total: $ 5.37
Grand total: $ 8.63
Siehst du den Fehler? Wir müssen auf Rundungsfehler achten! Schaue dir dieses Beispiel an, es scheint, als sollte die Gesamtsumme $ 8.62
sein, aber das ist es nicht.
Die Ausgabeformatierung ändert nicht die Zahl, sondern nur die Ausgabe! Wenn wir die Ausgabeformatierung dahingehend geändert haben, dass sie drei Nachkommastellen enthält, wird der Grund für den Fehler offensichtlicher:
Cost: $3.070
Tax: 0.184
-------------
Total: $3.254
Cost: $5.070
Tax: 0.304
-------------
Total: $5.374
Grand total: $8.628
Auch hier ändert die Formatierung der Anzeige nichts an der Zahl. Verwende die Anweisung round
, um den Wert zu ändern und wirklich zu runden. Siehe unten:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | cost1 = 3.07
tax1 = round(cost1 * 0.06, 2)
total1 = cost1 + tax1
print(f"Cost: ${cost1:5.2f}")
print(f"Tax: {tax1:5.2f}")
print(f"-------------")
print(f"Total: ${total1:5.2f}")
cost2 = 5.07
tax2 = round(cost2 * 0.06, 2)
total2 = cost2 + tax2
print()
print(f"Cost: ${cost2:5.2f}")
print(f"Tax: {tax2:5.2f}")
print(f"-------------")
print(f"Total: ${total2:5.2f}")
print()
grand_total = total1 + total2
print(f"Grand total: ${grand_total:5.2f}")
|
Cost: $ 3.07
Tax: 0.18
-------------
Total: $ 3.25
Cost: $ 5.07
Tax: 0.30
-------------
Total: $ 5.37
Grand total: $ 8.62
Die Rundungsanweisung steuert, auf wie viele Stellen nach der Dezimalstelle gerundet wird. Der gerundete Wert wird zurückgegeben, der ursprüngliche Wert wird jedoch nicht geändert. Siehe unten:
1 2 3 4 5 6 | x = 1234.5678
print(round(x, 2))
print(round(x, 1))
print(round(x, 0))
print(round(x, -1))
print(round(x, -2))
|
Siehe unten, wie sich die Eingabe der round()
-Funktionswerte wie -2 auf die Nachkommastellen auf die Ausgabe auswirkt:
1234.57
1234.6
1235.0
1230.0
1200.0
33.7. Verwendung in Arcade-Programmen¶
Wir müssen nicht nur Zeichenfolgen für Ausgabeanweisungen formatieren. Das Beispiel timer.py verwendet die Formatierung von Zeichenfolgen, um einen On-Screen-Timer zu erstellen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | def on_draw(self):
""" Use this function to draw everything to the screen. """
# Start the render. This must happen before any drawing
# commands. We do NOT need an stop render command.
arcade.start_render()
# Calculate minutes
minutes = int(self.total_time) // 60
# Calculate seconds by using a modulus (remainder)
seconds = int(self.total_time) % 60
# Figure out our output
output = f"Time: {minutes:02d}:{seconds:02d}"
# Output the timer text.
arcade.draw_text(output, 300, 300, arcade.color.BLACK, 30)
def update(self, delta_time):
"""
All the logic to move, and the game logic goes here.
"""
self.total_time += delta_time
|
Du kannst den Programmcode auch verwenden, um die Punktzahl oder andere Statistiken anzuzeigen, die du dem Spieler anzeigen möchten.