Link Search Menu Expand Document

Ausgaben formatieren

Bisher haben wir das so gemacht:

s = 'Katze'
a = 11
print("Die "+ s + " ist " +str(a) +" Jahre alt.")

Oft aber wollen wir mehr, wir wollen etwa eine gewisse Zahl von Nachkommastellen für float-Zahlen, mit oder ohne vorzeichen etc.

Es gibt für String-Objekte, das Platzhalter enthält, die Methode ‘format’, der man eine beliebige Anzahl von Argumenten übergeben kann, die dann nach gewissen Regeln für die Platzhalter eingesetzt werden. Im einfachsten Fall werden Sie nach der Reihenfolge eingesetzt:

print("Die Länge der {} ist {} {}".format('Strecke', 213.12312, 'Meter'))
Die Länge der Strecke ist 213.12312 Meter
print("Die Länge der {:10s} ist {:.2f} {:10s}.".format(
    'Strecke', 213.12312, 'Meter'))
# Strings in Felder der Länge 10 einsetzen, Fließkommazahl mit zwei Nachkommastellen.
Die Länge der Strecke    ist 213.12 Meter     .
print("Die Länge der {} ist {:.2e} {}".format('Strecke', 213.12312, 'Meter'))
Die Länge der Strecke ist 2.13e+02 Meter

Die einfachste Version von Platzhalter hat die Form:

 {:[sign][width][.precision]type}

Dabei kann man jeden der Teile in eckigen Klammern weglassen. width beschreibt die Breite des Felds, precision die Anzahl der Nachkommastellen. Ist sign das Zeichen +, so werden Vorzeichen (von Zahlen) immer mit ausgegeben, ist es -, so werden nur negative Vorzeichen ausgegeben. Achtung: Benötigt die Zahl für ihre Darstellung eine größere Breite als width, wird sie breiter ausgegeben.

wobei type eines der folgenden Zeichen ist:

Strings:

s 	String format. This is the default type for strings and may be omitted.

Das s kann man weglassen, da Python das Format aus dem Typ erschließt.

Integers:

b 	Binary format. Outputs the number in base 2.
c 	Character. Converts the integer to the corresponding
    unicode character before printing.
d 	Decimal Integer. Outputs the number in base 10.
o 	Octal format. Outputs the number in base 8.
x 	Hex format. Outputs the number in base 16, using
    lower- case letters for the digits above 9.
X 	Hex format. Outputs the number in base 16, using
    upper- case letters for the digits above 9.
n 	Number. This is the same as 'd', except that it uses
    the current locale setting to insert the appropriate
    number separator characters.

Steht kein Zeichen, so bedeutet das für Integers ‘d’.

Floats:

'e' 	Exponent notation. Prints the number in scientific
        notation using the letter ‘e’ to indicate
        the exponent. The default precision is 6.
'E' 	Exponent notation. Same as 'e' except it uses an upper
        case ‘E’ as the separator character.
'f' 	Fixed point. Displays the number as a fixed-point
        number. The default precision is 6.
'F' 	Fixed point. Same as 'f', but converts nan to NAN and
        inf to INF.
'g' 	
        General format. For a given precision p >= 1, this rounds the number to p significant digits and
        then formats the result in either fixed-point format or in scientific notation, depending on
        its magnitude. The precise rules are as follows: suppose that the result formatted with presentation
        type 'e' and precision p-1 would have exponent exp. Then if -4 <= exp < p, the number is formatted
        with presentation type 'f' and precision p-1-exp. Otherwise, the number is formatted with
        presentation type 'e' and precision p-1. In both cases insignificant trailing zeros are removed
        from the significand, and the decimal point is also removed if there are no remaining digits
        following it.

        Positive and negative infinity, positive and negative zero, and nans, are formatted as inf, -inf, 0,
        -0 and nan respectively, regardless of the precision.

        A precision of 0 is treated as equivalent to a precision of 1. The default precision is 6.
'G' 	General format. Same as 'g' except switches to 'E' if the number gets too large. The
        representations of infinity and NaN are uppercased, too.
'n' 	Number. This is the same as 'g', except that it uses the current locale setting to
        insert the appropriate number separator characters.
'%' 	Percentage. Multiplies the number by 100 and displays in fixed ('f') format, followed
        by a percent sign.

Steht kein Zeichen, so ist das ähnlich wie g, allerdings wird dafür gesorgt, dass in der Dezimaldarstellung mindestens eine Vorkommastelle steht.

import math
print('Der Wert beträgt {:.10f}'.format(math.pi))
Der Wert beträgt 3.1415926536
print('Der Wert beträgt {:n}'.format(math.pi))
Der Wert beträgt 3.14159

Was hat es mit locale auf sich?

import locale
locale.getdefaultlocale()
('de_DE', 'cp1252')
print('Der Wert beträgt {:n} .'.format(math.pi))
Der Wert beträgt 3.14159 .
locale.setlocale(locale.LC_ALL, "de_DE.utf8")
'de_DE.utf8'
print('Der Wert beträgt {:n} .'.format(math.pi))
Der Wert beträgt 3,14159 .
print('Der Wert beträgt {:n} .'.format(12346756765))
Der Wert beträgt 12.346.756.765 .
locale.setlocale(locale.LC_ALL, "C")
'C'
print('Der Wert beträgt {:n} .'.format(math.pi))
Der Wert beträgt 3.14159 .
print('Der Wert beträgt {:n} .'.format(12346756765))
Der Wert beträgt 12346756765 .

Übergabe von Werten mit Feldnamen

In den oben geschilderten Formatspezifikationen lassen sich auch ‘keywords’ vor den Namen schreiben. Dann können die zu formatierenden Werte an .format(…) mit keywords übergeben werden, was oft lesbarer ist. Also ein Beispiel von vorhin mit dieser Form:

print("Die Länge der {name:10s} ist {length:.2f} {unit:10s}.".format(
    name='Strecke', length=213.12312, unit='Meter'))
Die Länge der Strecke    ist 213.12 Meter     .

Weitere Details zur Formatierung

Formatstrings des neuen Typs enthalten Platzhalter, die in geschweifte Klammern {} eingeschlossen sind (statt %). Ansonsten ist das Format durch folgende Grammatik charakterisiert:

Platzhalter       ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
arg_name          ::=  [identifier | integer]
attribute_name    ::=  identifier
element_index     ::=  integer | index_string
index_string      ::=  <any source character except "]"> +
conversion        ::=  "r" | "s" | "a"
format_spec       ::=  siehe unten

und die Formatspezifizierung format_spec so:

format_spec ::=  [[fill]align][sign][#][0][width][,][.precision][type]
fill        ::=  <any character>
align       ::=  "<" | ">" | "=" | "^"
sign        ::=  "+" | "-" | " "
width       ::=  integer
precision   ::=  integer
type        ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

Was ist das und wie ist es zu lesen?

Es handelt sich um eine Backus-Naur-Form für die (kontextfreie) Grammatik solcher Ausdrücke. Was kompliziert klingt und aussieht, ist im Kern ganz einfach. Man beginnt mit dem Ausdruck, den es zu erklären gilt Platzhalter auf der linken Seite oben. Durch ::= wird definiert, was dafür eingesetzt werden kann, dabei stehen wieder [ ] für Teile, die man weglassen kann undsteht für “oder”.

Auf der rechten Seite stehen entweder bestimmte Zeichen oder Typen, dann wissen wir, was gemeint ist, oder aber es stehen wieder zunächst unverständliche Ausdrücke. In diesem Fall müssen wir nun wieder auf der linken Seite nach diesen Ausdrücken suchen. So finden wir wieder eine Definition ::=, durch die wir den Ausdruck ersetzen können. Auf diese Weise werden alle möglichen Ausdrücke beschrieben.

Keine Angst, unten stehen viele Beispiele, mit denen man es genausogut begreifen kann, ohne sich auf die Backus-Naur-Form einzulassen. So steht diese aber in der offiziellen Dokumentation: Es ist also nützlich, sie lesen zu können oder zumindest nicht abgeschreckt zu sein.

Diese Form erklärt aber nur die Syntax, nicht die Semantik, d.h. Bedeutung der Ausdrücke. Dazu braucht es weitere Erklärungen. Die vollständigen Erklärungen finden sich unter https://docs.python.org/3/library/string.html, ich erkläre nur einen Teil davon per Beispiel.

Hier soll nur ein Beispiel für die weiteren Möglichkeiten stehen, die das Beispiel von vorhin nochmal um Füllzeichen und rechts- bzw. linksbündige Ausrichtung erweitert:

for name,length,unit in zip(['Strecke','Katze','Straße'],[213.123,33.335,123213.32],['Meter','Daumenbreit','Centimeter']):
    print("Die Länge der {name:-<10s} ist {length:10.2f} {unit:-<12s}.".format(
        name=name, length=length, unit=unit))
Die Länge der Strecke--- ist     213.12 Meter-------.
Die Länge der Katze----- ist      33.34 Daumenbreit-.
Die Länge der Straße---- ist  123213.32 Centimeter--.

Noch eine ander Art der Formatierung: f-Strings (Python >= 3.6)

Diese Art der Formatierung wurde erst in Python 3.6 eingeführt, s.:

https://www.python.org/dev/peps/pep-0498/

Dabei wird eine neue Art von Strings eingeführt, bei denen ein f vor den Anführungszeichen steht. Alle Ausdrücke in geschweiften Klammern werden dann evaluiert und das Ergebnis an dieser Stelle in den f-String eingesetzt; das Ergebnis ist ein gewöhnlicher String. Die Ausdrücke können noch durch eine Formatspezifikation erweitert werden, wie wir sie schon kennen, etwa :.3f. Sehen wir uns einige Beispiele an:

tier = "Die Katze"
objekt = "der Matte"
satz = f"{tier} sitzt auf {objekt}"

print(satz)
Die Katze sitzt auf der Matte
f"{tier} ist {laenge:.2f} Meter und damit {laenge/0.9144:.2f} yards lang."
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-17-5f98b1acdabc> in <module>
----> 1 f"{tier} ist {laenge:.2f} Meter und damit {laenge/0.9144:.2f} yards lang."


NameError: name 'laenge' is not defined

Wenn nicht zufällig vorher schon eine Variable ‘laenge’ definiert wurde, gibt es einen Fehler.

Achtung: Nur, wenn die Ausdrücke in geschweiften Klammern korrekt evaluiert werden können, wird der f-String ohne Fehler ausgewertet.

laenge = 0.7
f"{tier} ist {laenge:.2f} Meter und damit {laenge/0.9144:.2f} yards lang."
'Die Katze ist 0.70 Meter und damit 0.77 yards lang.'
import numpy as np
radius = 1.23
f"Ein Kreis des Radius {radius:.2f} hat einen Flächeninhalt von {np.pi*radius**2:.2f}."
'Ein Kreis des Radius 1.23 hat einen Flächeninhalt von 4.75.'