basics michael poeltl © 2011,2013-2015

format()

ist zum einen eine Funktion, die ein str-Objekt retourniert, und zum anderen ist es eine Methode an einem str-Objekt, die den früher üblichen Einsatz der Formatierungs ablöst.
Bis zur Einführung von format() verwendete man ausschließlich die (auch in C bestens bekannten) Formatstrings (%s, %d, %f, etc).
Das ist in python zwar immer noch möglich, ist aber bald schon (so glaube ich) getagged als deprecated, da die Zukunft der format()-Methode/Funktion gehört.
Mit Formatstrings schrieb man:

>>> print( "ich bin %d Jahre alt" % (20) )
ich bin 20 Jahre alt
>>>

was immer noch funktioniert, aber ein Auslaufmodell darstellt (aus meiner Sicht). Mit format() sieht die Codezeile so aus:

>>> print( "ich bin {} Jahre alt".format(20) )
ich bin 20 Jahre alt
>>>

Wir betrachten also in punkto String-Formatierung nur diese str-Methode/built-in-function ''.format()/format() an Stelle der Formatstrings - (gleich von Anfang an das aktuelle einlernen, und das alte kann dir in der einen oder anderen code-Passage älterer Programme begegnen, was trotzdem lesbar und nachvollziehbar bleibt).

Da ich format() eigentlich nur als Methode an einem str-objekt kennengelernt habe und auch nur so einsetze, möchte ich hier die Gelegenheit wahrnehmen, darauf hinzuweisen, dass format() eben auch eine built-in-function ist!

>>> help( format )
Help on built-in function format in module builtins:

format(...)
    format(value[, format_spec]) -> string
    
    Returns value.__format__(format_spec)
    format_spec defaults to ""
(END)
>>> help( ''.format )
Help on built-in function format:

format(...)
    S.format(*args, **kwargs) -> str
    
    Return a formatted version of S, using substitutions from args and kwargs.
    The substitutions are identified by braces ('{' and '}').
(END)

lieferte zwei unterschiedliche Hilfetexte. Bevor wir mit print() in Kombination mit der format-Methode weiermachen, hier noch kleine Beispiele für die format()-Funktion.

>>> zahl = 11823.73592
>>> format( zahl, '0.2f' )
'11823.74'
>>>

Leider ist die Ausgabe nicht an die locale gebunden. Eine floating-point-Zahl wird immer den Punkt als Komma haben. Ein workaround kann die translate()-methode an einem str-objekt sein.

>>> punkt_comma= {ord('.'):',', ord(','):'.'}
>>> format(zahl, '0,.2f').translate(punkt_comma)
'11.823,74'
>>>

Ich muss auch 'mal nachschauen, welche Funktionen das locale-Modul für diesen Zweck zur Verfügung stellt.

.

Die format()-function ist auch hilfreich, wenn man bei der Umwandlung eines Integers in binary-format den 0b-prefix nicht haben will.

>>> ganze_zahl = 234
>>> print( bin( ganze_zahl ))
0b11101010
>>> print( format( ganze_zahl, 'b' ))
11101010
>>>

Das geht freilich auch für Octal-Zahlen und für Hexadezimalzahlen.

>>> print( ganze_zahl )
234
>>> print( oct( ganze_zahl ))
0o352
>>> print( format( ganze_zahl, 'o' ))
352
>>> print( hex( ganze_zahl ))
0xea
>>> print( format( ganze_zahl, 'x' ))
ea
>>>

Das geht auch für signed Intgers.

>>> print( hex( -ganze_zahl ))
-0xea
>>> print( format( -ganze_zahl, 'x' ))
-ea
>>>

ODER - falls man einmal eiinen integer als 32-bit-lange Zahl darstellen möchte, dann könnte man das so bewerkstelligen.

>>> print( format( 2**31 + ganze_zahl, 'b' ))
10000000000000000000000011101010
>>>

Aber weiter im Text - nun der Fokus auf format()-method.

>>> a, b, c = 1, 2, 3,
>>> print( a, b, c )
1 2 3
>>> print( a, b, c, sep='|' )
1|2|3
>>> print( a, b, c, sep='|',end='UUU\n\n' )
1|2|3UUU
>>>

okay - wir sehen schon, dass die Argumentenliste der print()-function eine unbestimmte Länge hat. Schön zu sehen ist, dass wir einen separator setzen können und einen endstring explizit angeben können.

Wenn du dir das manual für print() aufmachst (help( print )), dann siehst Du schon

>>> help(print)
Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

sep-end-file mit ihren default-Werten. Ich würd sagen, mit file warten wir noch zu. Die Voreinstellung sieht eine Ausgabe nach stdout vor, und das passt uns in den meisten Fällen sowieso.

Mit Platzhalter-Feldern (replacment-fields), die durch braces gesetzt werden, lässt sich gut arbeiten.

>>> print( 'a = {}'.format(a),'b = {}'.format(b), 'c = {}'.format(c),sep=' | ' )
a = 1 | b = 2 | c = 3
>>>

Ohne Angabe der Position innerhalb der braces werden die Argumente der format()-Methode der Reihe nach den jeweiligen {} zugewiesen. Das lässt sich steuern, wenn man die Position des Arguments in der Argumentenliste der format()-Methode angibt.

>>> print( 'a = {}, b = {}, c = {}'.format( a,b,c ) )
a = 1, b = 2, c = 3
>>> print( 'a = {0}, b = {1}, c = {2}'.format( a,b,c ) )
a = 1, b = 2, c = 3
>>> print( 'a = {0}, b = {1}, a = {0}'.format( a,b,c ) )
a = 1, b = 2, a = 1
>>> print( '{0}{1}{0}'.format( 'abra', 'cad' ) )
abracadabra
>>>

es geht automatisch (keine Angabe innerhalb der geschweiften Klammern) und manuell (Angabe einer Position) - das darf man aber nicht mixen, denn sonst krachts im Gebälk.

>>> print( '{2} und {} und {1}'.format( 1,2,3,4,5 ) )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot switch from manual field specification to automatic field numbering
>>>

Da gibt es natürlich wieder eine Syntax im Feld, die sich auf die Ausgabe auswirkt und so aussieht:

{ [field_name] [! conversion] [: format_spec] }

field_name ist keyword oder Positionsangabe.

>>> print( "P1 hat Koordinaten ({x1}/{y1})".format( x1='22,56',y1='-28.0' ) )
P1 hat Koordinaten (22,56/-28.0)
>>>

das funktioniert zwar, schaut aber alles andere als praktisch aus - viel eher denkt man da ein dictionary- zum Beispiel:

>>> koordinaten = {'x1':'22.56', 'y1':'-28.0', 'x2':'1.22', 'y2':'7.92'}
>>> print( 'P2 hat die Koordinaten ({x2}/{y2})'.format( **koordinaten ) )
P2 hat die Koordinaten (1.22/7.92)
>>>

ist das nicht herrlich?!!
(die mit zwei Sternen eingeleiteten Angaben sind die keyword-Argumente, die wir noch genauer bei den Funktionen besprechen werden bzw. eh schon besprochen haben - es gibt auch Argumente, die mit einem * eingeleitet werden, wie wir gleich sehen werden)

>>> print( 'die Frage nach dem 5. Buchstaben ({4}) und dem 2. Buchstaben ({1}) ist unerheblich!'.format( *'michaelpoeltl' ) )
die Frage nach dem 5. Buchstaben (a) und dem 2. Buchstaben (i) ist unerheblich!
>>>

CoOOL!
Sequenzen (str, listen, tuple) bekommen einen *, wenn man diese als Argument mit unbekannter Länge einbinden will.
conversion ist etnweder repr() --> r ODER str() --> s

>>> print( "repr() shows quotes: {!r}; str() doesn't: {!s}".format( 'test1', 'test2' ) )
repr() shows quotes: 'test1'; str() doesn't: test2
>>>

Als nächstes wollen wir uns näher ansehen:
format_spec, decimal precision, field width, alignment und padding.

>>> print ('wert ist {:f}'.format(234.223344))
wert ist 234.223344
>>> print ('wert ist {:.2f}'.format(234.223344))
wert ist 234.22
>>> print ('wert ist {:20.2f}'.format(234.223344))
wert ist               234.22
>>> print ('wert ist {:<20.2f}'.format(234.223344))
wert ist 234.22              
>>> print ('wert ist {:^20.2f}'.format(234.223344))
wert ist        234.22       
>>> print ('wert ist {:>20.2f}'.format(234.223344))
wert ist               234.22
>>>

: trennt den Formatierungsteil vom field-name
das Runden auf X Stellen war dir wahrscheinlich eh schon bekannt.
ausrichten geht also mittels < == linksbündig, ^ == center, > == rechtsbündig

>>> print ('{0:<20}'.format('michael'),'{0:^20}'.format('franz'),'{0:>20}'.format('poeltl'),sep='')
michael                    franz                      poeltl
>>> print ('{0:X<20}'.format('michael'),'{0:x^20}'.format('franz'),'{0:X>20}'.format('poeltl'),sep='')
michaelXXXXXXXXXXXXXxxxxxxxfranzxxxxxxxxXXXXXXXXXXXXXXpoeltl
>>>

Beim Zweiten Mal gab ich noch ein Füllzeichen an.
Füllzeichen kann eigentlich alles sein, ausser }.
und noch ein banaleres Beispiel:

>>> speiseplan = [
...               ('Montag', 'Schnitzel'),
...               ('Dienstag', 'Krautfleckerl'),
...               ('Mittwoch', 'Germknoedel'),
...               ('Donnerstag','Gemuesesuppe')
...              ]
>>> in_form = '{tag:15} {speise:15}'
>>> for tag, speise in speiseplan:
...     print (in_form.format(tag=tag, speise=speise))
...
Montag          Schnitzel
Dienstag        Krautfleckerl
Mittwoch        Germknoedel
Donnerstag      Gemuesesuppe
>>>

oder so

>>> in_form = '{tag:>15} {speise:15}'
>>> for tag, speise in speiseplan:
...     print (in_form.format(tag=tag, speise=speise))
...
         Montag Schnitzel
       Dienstag Krautfleckerl
       Mittwoch Germknoedel
     Donnerstag Gemuesesuppe
>>>

Für float hatten wir f - welche Bezeichner gibt es da denn noch?

d       decimal
b       binaer
c       char (eine Zahl wird durch das zugehörige unicode-Zeichen
        dargestellt
e,E     exponentiale Schreibweise
f,F     float
g,G     ist default; System wählt selber
        beste Darstelllung für Gleitkommazahl aus
n       hexazahl
o       octalzahl
%       Zahl wird mit 100 multipliziert und als Prozentzahl mit
        Festkommazahl und Prozentzeichen am Ende dargestellt

wollen wir das nun in ein paar Beispiele gießen.

>>> print ('Der Zuwachs betraegt {:%}'.format(223./582))
Der Zuwachs betraegt 38.316151%
>>> print ('Der Zuwachs betraegt {:.2%}'.format(223./582))
Der Zuwachs betraegt 38.32%
>>> print ('Der Zuwachs betraegt {:+.2%}'.format(223./582))
Der Zuwachs betraegt +38.32%
>>>

Mit dem zusätzlichen + werden in jedem Fall vorzeichen angegeben (also auch bei positiven Werten). Nutzt man stattdessen ein - (Minus), dann werden nur negative Zahlen mit Vorzeichen versehen, und gibt man ein Leerzeichen an, dann steht vor Minus noch ein Leerzeichen und bei positiven Zahlen wird nur ein Leerzeichen eingefügt (ist praktisch für richtige Formatierung).

Man kann auch einfache Tabellen bauen.
Man nehme eine for-Schleife, die 1 bis 10 nimmt und pro Durchgang folgendes ausgibt:
i i*i i*i*i
OHNE Manipulation sähe das so aus:

>>> for i in range(1,11):
...   print ('{} {} {}'.format(i,i*i,i*i*i))
... 
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
>>>

Da kommen Zeichen einander sehr nahe. Und durch Einfügen eines kleinen Details ist die tabellarische Ausgabe auf einmal schön nach der größten Zahl (4-stellig, 2-stellig,etc) übersichtlich.

>>> for i in range(1,11):
...   print ('{:2d} {:3d} {:4d}'.format(i,i*i,i*i*i))
... 
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
>>>

Du erkennst gleich den gravierenden Unterschied der zwei letzten Beispiele.

Was wenn geschweifte Klammern ausgegeben werden sollen?
dann geht das mittels {{ {} }}

>>> print ('hello braces {{{0} {1}}}'.format('eins', 'zwei'))
hello braces {eins zwei}
>>>

schaut komisch aus, nicht wahr?

>>> print ('{{}}'.format(1))
{}
>>> print ('{{{}}}'.format(1))
{1}
>>>

Das sollt für's Erste reichen; schau dir zum Thema auch noch das pprint-Modul (Teil der StandardLibrary; pprint steht für pretty print) an; das nutzt man, wenn man verschachtelte dicts oder lists etc. schön auf den Bildschirm ausgeben lassen will.

Noch 'was zum Schmunzeln:

>>> def log(*args):
...   for i,arg in enumerate(args,1):
...     print("Argument {}: {}".format( i,arg ))
... 
>>> log('eins',2,'drei',(22,33,'a'))
Argument 1: eins
Argument 2: 2
Argument 3: drei
Argument 4: (22, 33, 'a')
>>>
>>> print( "ein key-test fuer format-method: {key}".format( key='"irgenein Argument"' ) )
ein key-test fuer format-method: "irgenein Argument"
>>>
>>> euro = 22
>>> print('hier we go {euro}'.format(euro=euro) )
hier we go 22
>>>

Falls format() mehr Argumente übergeben bekommt, als als Platzhalter im Text gibt, dann werden die Überzähligen Argumente einfach ignoriert.

>>> print("hallo {}".format( 'michael','poeltl'))
hallo michael
>>>
>>> def mitte(text,padding='=',width=40):
...     return '{0:{1}^{2}}'.format(text,padding,width)
... 
>>> print( mitte( 'keine Ahnung' ))
==============keine Ahnung==============
>>> print( mitte(' bessere zeiten ', padding='+',width=60))
++++++++++++++++++++++ bessere zeiten ++++++++++++++++++++++

Hier geht es zum Seitenanfang und da geht es zur python-Startseite