Empfohlene Unterrichtsinhalte als Vorbereitung für dieses Thema: 02-01/2/3/4 (Variablen, Strings, Listen, Integers und Floats), 03-03 (Schleifen)

Einführung in die computerlinguistische Programmierung mit Python 📖

10-01: String Formatting 🗳️

Wie ihr wisst, können die Datentypen, mit denen wir zu tun haben, mit der Methode str() explizit in Strings umgewandelt werden. So können wir Strings und Nicht-Strings mit dem +-Operator zusammenfügen und schließlich als einen konkatenierten String ausgeben:

Es gibt einen sehr viel bequemeren Mechanismus, um Nicht-Strings in Strings einzubauen, und zwar die Methode format(). format() ist eine Stringmethode und nimmt beliebig viele Argumente an. Die Methode wird folgendermaßen verwendet:

Die Methode format() operiert auf einem String in dem Platzhalter {} enthalten sind und nimmt Werte entgegen, die dann an Stelle der Platzhalter in den String eingesetzt werden. Dabei erfolgt die Typenumwandlung der jeweiligen Werte automatisch.

Somit können wir auf das Zusammensetzen von Strings und Nicht-Strings mit dem +-Operator verzichten.

Grundsätzlich werden die format()-Argumente in ihrer angegebenen Reihenfolge in den String eingesetzt. Sie lassen sich aber auch an Hand ihrer Position im Format-String referenzieren.

Die nicht benötigten Argumente, die an format() übergeben werden, werden ignoriert.

Formatierung und komplexe Datentypen

Wir müssen nicht immer einzelne Argumente für die format()-Methode bereitstellen. Wir können auch Elemente aus strukturiertenn Datentypen (Listen, Dictionaries, Tupel) verarbeiten, die wir beispielsweise als Rückgabewert von anderen Funktionen erhalten, um diese in übersichtlicherer oder besser lesbarer Form auszugeben.

Listen

Elemente aus Listen in Format-Strings eingesetzt werden in dem man die Liste als Argument ein benanntes Argument übergibt. Über den Argumentnamen können wir dann auf per Indexing auf die Listenelemente zugreifen.

Hier erhält data den Wert der vorher definierten Liste und wir können im Format-String Elemente der Liste mit Bezug auf den Namen des Arguments einsetzen lassen. Die gescheiften Klammern bewirken hier, dass data in diesem Fall nicht nur als einfacher String interpretiert wird, der in den formatierten String übernommen wird.

Wenn eine Liste als unbenanntes Argument übergeben wird, können wir auf deren Elemente mit Hilfe ihres Index entsprechend der Position in der Argumentliste zugreifen.

Die 0 referenziert die Liste constituents, die als nulltes Argument an format() übergeben wurde.

Man kann Elemente aus Sequenzen auch mit weniger Schreibarbeit als Argumente an die format()-Methode übergeben. Dabei hilft der Unpacking-Operator *: Die Elemente der Liste werden als einzelne unbenannte Argumente an die format()-Methode übergeben.

Der Code mit dem * oben entspricht dem folgenden Code, in dem alle Argumente einzeln durch Komma getrennt übergeben werden:

Mit Hilfe von Indexangaben können bestimmte Elemente aus einer längeren Liste ausgewählt werden um in den String eingefügt zu werden.

Dictionaries

Wie Listen können wir auch Dictionaries an die format()-Methode übergeben. Auch hier haben wir verschieden Möglichkeiten. Wir können ein Dictionary als benanntes Argument übergeben und dann mit Hilfe der Schlüssel auf einezelne Werte zugreifen.

Um auch hier lässt sich mit Hilfe eines weiteren Unpacking Operators ** speziell für Dictionaries Schreibarbeit sparen: Die Schlüssel-Wert-Paare des Dictionaries werden so behandelt als wären sie als einzelne benannte Argumente an format[] übergeben worden.

Der ** führt so dazu, dass der Code oben dem folgenden Code mit mehreren benannten Argumenten entspricht:

Wenn wir im Zusammenhang mit Dictionaries den einfachen *-Operator einsetzen, können wir Format-String nicht mehr die Schlüssel benutzen um auf die Werte referenzieren. Stattdessen werden nur die Schlüssel selbst als unbenannte Argumente bereitgestellt.

Mehr Informationen zu den Operatoren: Unpacking Operators in Python

Achtung! Zu wenige Argumente machen Probleme

Wenn wir weniger Argumente bereitstellen als Platzhalter in unserem Format-String vorhanden sind, wirft der Interpreter einen Fehler.

Dieser Fall muss abgefangen werden, wenn wir größere Datenmengen verarbeiten und format() mit automatisch erstellten Sequenzen gefüttert wird.

Formatierungs-Syntax

Padding und Alignment

Über eine spezielle Syntax für Format-String-Platzhalter lassen sich auch die Ausrichtung der Ausdrücke und der umgebende Whitespace beeinflussen. Grundsätzlich wird genau soviel Platz für einen einzusetzenden Ausdruck benutzt wie nötig ist. Wir können aber können aber auch eine bestimmte Länge für einen Platzhalter reservieren.

Der Doppelpunkt innerhalb der geschweiften Klammern zeigt an, dass an dieser Stelle die Formatierungsinformationen folgen.

Wenn der einzusetzende String mehr als den vorgegebenen Raum benötigt wird die Vorgabe ignoriert.

Per Default wird der einzusetzende Ausdruck innerhalb seines Slots links ausgerichtet. Wir können explizit andere Ausrichtungen erzwingen:

Falls die Länge des Whitespace beim Zentrieren einer ungeraden Zahl von Zeichen entspricht, wird der rechte Whitespace entsprechend um ein Zeichen länger als der linke.

An Stelle von Whitespace können wir auch ein anderes Zeichen festlegen, mit dem dann der Whitespace gefüllt wird.

Das Padding Zeichen, hier = wird direkt hinter dem : und noch vor der Ausrichtung in der Formatspezifizierung angegeben.

Zahlen Formatierung

Auch Zahlen können mit Format-Strings besser dargestellt werden.

Grundsätzlich werden alle Nachkommastellen von Floats angezeigt, …

… aber es kann zu Rundungsfehlern kommen.

Mit dem Zeichen f können wir explizit die Formatierung als Float erzwingen. Dann werden sechs Nachkommastellen ausgegeben und es wird entsprechend gerundet:

Wir können die Genauigkeit der Float-Ausgabe anpassen, indem wir die Anzahl der Nachkommastellen vorgeben:

Der . und die darauf folgende Zahl (hier 4) bestimmten die Anzahl der Dezimalen.

Wir können wie bei Strings eine Gesamtlänge für Zahlen festlegen und den führenden Whitespace mit Nullen füllen.

Außerdem können wir festlegen wir Vorzeichen dargestellt werden sollen. Per Default wird nur bei negativen Zahlen (notwendigerweise) das Vorzeichen angezeigt.

Ein Leerzeichen nachdem Formatierungszeichen : sorgt dafür, dass ein Space für eventuelle negative Vorzeichen reserviert wird. Ein + an der gleichen Stelle erzwingt ein Vorzeichen auch bei positiven Zahlen. Das Formatierungszeichen d erzwingt, dass der als Argument gegebene Wert als Dezimalzahl dargestellt wird.

Die Vorzeichendarstellung und Padding angaben können kombiniert werden. Das Vorzeichen wird dabei als ein Zeichen der Gesamtlänge des Ausdrucks berücksichtigt.

Die Zahl vor dem Dezimalsystem-Symbol d bestimmt die wieviele Zeichen für die einzusetzenden Zahl reserviert wird. Mit dem = direkt nach dem : können wir beinflussen ob Vorzeichen links oder rechts vom Padding-Space ausgegeben werden. Wir können auch weiterhin führende Nullen erzwingen; dafür fügen wir vor der Längenangabe des Ausdrucks wieder eine 0 ein.

Formatierte Ausgabe anderer Datentypen

Falls wir Werte komplexer Datentypen ausgeben lassen wollen, müssen wir beachten, dass sich diese anders als Werte von Zahldatentypen und Strings nicht direkt mit den o.g. Werkzeugen formatieren lassen. Wenn wir die Werte zunächst explizit in Strings umwandeln, können wir sämtliche Formatierungsoptionen ebenfalls nutzen.

Der Konversionsoperator ! zusammen mit der Formatangabe s für String entspricht der Anwendung str()-Funktion auf den übergebenen Wert:

Escapen von geschweiften Klammern in Format-Strings

Es kann vorkommen, dass wir in unserem Format-String geschweifte Klammern von der Interpretation als Platzhalter ausnehmen wollen. Durch das doppeln der Klammern {{...}} werden die inneren Klammern als normaler Text interpretiert:

Kaskadierende Format-Strings

Mit Hilfe von kaskadierenden Format-Strings können wir zum Beispiel Listen mit variabler Länge ausgeben lassen.

Wir wenden format() mehrmals hintereinander an um die Inhalte mit der gewünschten Formatierung auszugeben.

Hier ist eine Variante in der sich die Namenspaare und die benutzten Verben nicht wiederholen sollen.

Vorsicht! Abhängig von den übergebenen Argumenten kann es zu Probleme kommen.

F-Strings

Eine neuere Methode um Strings zu formatieren sind die F-Strings (ab Python 3.6, 2015). Sie sind noch etwas flexibler als die format()-Methode, die mit Python 3.0 2008 eingeführt wurden. F-Strings machen es noch einfacher Platzhalter mit Werten anderer Variablen zu füllen. Darüber hinaus werden F-Strings effizienter verarbeitet.

Der Python-Interpreter erkennt das Signal-Präfix f vor dem String, das den f-Strings ihren Namen gibt. Anschließend werden wie oben die Ausdrücke in geschweiften Klammern als Platzhalter mit Formatierungs Informationen verarbeitet. Vorsicht! Die Platzhalter dürfen anders als bei Format-Strings nicht leer sein. Außerdem dürfen F-String-Platzhalter keine Backslashes \ enthalten.

Der Interpreter ist dabei auch in der Lage Variablennamen, Funktionen und andere Operationen zu erkennen, diese werden zunächst ausgewertet. Anschließend werden die resultierenden Werte, wenn möglich, zu Strings konvertiert und zuletzt werden alle Teil-Strings verbunden.

Wenn wir auf Dictionary-Elemente zugreifen wollen, müssen wir beachten die Keys als Strings zu markieren. Dies ermöglicht wiederum, dass die Key-Werte auch aus anderen Variablen gelesen werden können.

Vorsicht! Die Markierung der Key-Strings darf nicht die gleiche sein, die für den F-String benutzt wird. Deshalb werden im obigen Beispiel einfache '...' und doppelte Anführungszeichen "..." benutzt.

Auf die Platzhalter der F-Strings sind alle Formatierungen anwendbar, die wir für Format-Strings kennengelernt haben.

Zusammenfassung

Weitere Themen dieser Woche