3 minute read

Today I’m going to write about formatting of strings in Python using format() function. Sending out a root mail(in BITS) got me inspired to write an article on it. So here’s something for my (and maybe even for your :wink:) future reference.

Basic formatting

' {} {}'.format('one', 'two')
' {} {}'.format(1, 2)

Output

$ one two
$ 1 2

You can give placeholders an explicit positional index.

' {1} {0}'.format('one', 'two')

Output

$ two one

Value conversion

The new-style simple formatter calls by default the __format__() method of an object for its representation. If you just want to render the output of str(…) or repr(…) you can use the !s or !r conversion flags.
Setup

class Data(object):

    def __str__(self):
        return 'str'

    def __repr__(self):
        return 'repr'
    def __format__(self):
        return 'format'

Input

' {0!s} {0!r} {}'.format(Data())

Output

$ str repr format

Padding and aligning strings

By default values are formatted to take up only as many characters as needed to represent the content. It is however also possible to define that a value should be padded to a specific length. Default alignment is left.

' {:10}!'.format('test')
' {:>10}!'.format('test')

Output

$       test!
$ test      !

By default string is being padded by space. But you can choose the padding character.

' {:!<10}'.format('test')

Output

$ test!!!!!!

You can align in center as well

' {:^10}!'.format('test')

Output

$    test   !

When using center alignment where the length of the string leads to an uneven split of the padding characters the extra character will be placed on the right side.

' {:^6}!'.format('zip')

Output

$  zip  !

Truncating long strings

Inverse to padding it is also possible to truncate overly long values to a specific number of characters.

' {:.5}'.format('shyamal')

Output

$ shyam

Combining truncating and padding

It is possible to combine truncating and padding.

' {:10.5}!'.format('shyamal')

Output

$ shyam     !

Numbers

It is possible to do padding with numbers.

' {:4d}'.format(42)

Output

$   42

Again similar to truncating strings the precision for floating point numbers limits the number of positions after the decimal point.

For floating points the padding value represents the length of the complete output. In the example below we want our output to have at least 6 characters with 2 after the decimal point.

' {:06.2f}'.format(3.141592653589793)

Output

$ 0034.14

Named placeholders

Setup

data = {'first': 'Shyamal', 'last': 'Vaderia'}

Input

' {last} {first}'.format(**data)

Output

$ Vaderia Shyamal

.format() also accepts keyword arguments.

' {first} {last}'.format(first='Jon', last='Snow!')

Output

$ Jon Snow!

Getitem and Getattr

New style formatting allows even greater flexibility in accessing nested data structures.

It supports accessing containers that support __getitem__ like for example dictionaries and lists:
Setup

person = {'first': 'Jean-Luc', 'last': 'Picard'}
data = [4, 8, 15, 16, 23, 42]

Input

' {p[last]} {p[first]}'.format(p=person)
' {d[4]} {d[5]}'.format(d=data)

Output

$ Picard Jean-Luc
$ 23 42

Setup

class Plant(object):
    type = 'tree'
    kinds = [{'name': 'oak', 'size': 'big'}, {'name': 'maple', 'size': 'small'}]

Input

' {p.type}: {p.kinds[0][name]}'.format(p=Plant())

Output

$ tree: oak

Datetime

Setup

from datetime import datetime

Input

' {:%Y-%m-%d %H:%M}'.format(datetime(2001, 2, 3, 4, 5))

Output

$ 2001-02-03 04:05

Parametrized formats

' {:.{prec}} = {:.{prec}f}'.format('Gibberish', 2.7182, prec=3)

Output

$ Gib = 2.718
' {:{width}.{prec}f}'.format(2.7182, width=5, prec=2)

Output

$  2.72
' {:{prec}} = {:{prec}}'.format('Gibberish', 2.7182, prec='.3')

Output

$ Gib = 2.72

Setup

from datetime import datetime
dt = datetime(2001, 2, 3, 4, 5)

Input

' {:{dfmt} {tfmt}}'.format(dt, dfmt='%Y-%m-%d', tfmt='%H:%M')

Output

$ 2001-02-03 04:05

Custom objects

The datetime example works through the use of the __format__() magic method. You can define custom format handling in your own objects by overriding this method. This gives you complete control over the format syntax used.

Setup

class HAL9000(object):

    def __format__(self, format):
        if (format == 'hodor'):
            return "Hold the door!!"
        return 'HAL 9000'

Input

' {:hodor}'.format(HAL9000())

Output

$ Hold the door!!

This post was originally written by me on gujjucoders.me.