Python String Formatting

From the Python 3 documentation The formatting operations described here (% operator) exhibit a variety of quirks that lead to a number of common errors [...]. Using the newer formatted string literals [...] helps avoid these errors. These alternatives also provide more powerful, flexible and extensible approaches to formatting text.

% operator

Prefer String Literals For new code, using str.format, or formatted string literals (Python 3.6+) over the % operator is strongly recommended.
>>> name = 'Pete'
>>> 'Hello %s' % name
# "Hello Pete"

We can use the %d format specifier to convert an int value to a string:

>>> num = 5
>>> 'I have %d apples' % num
# "I have 5 apples"

str.format

Python 3 introduced a new way to do string formatting that was later back-ported to Python 2.7. This makes the syntax for string formatting more regular.

>>> name = 'John'
>>> age = 20

>>> "Hello I'm {}, my age is {}".format(name, age)
# "Hello I'm John, my age is 20"

>>> "Hello I'm {0}, my age is {1}".format(name, age)
# "Hello I'm John, my age is 20"

Formatted String Literals or f-Strings

If your are using Python 3.6+, string f-Strings are the recommended way to format strings.

From the Python 3 documentation A formatted string literal or f-string is a string literal that is prefixed with `f` or `F`. These strings may contain replacement fields, which are expressions delimited by curly braces {}. While other string literals always have a constant value, formatted strings are really expressions evaluated at run time.
>>> name = 'Elizabeth'
>>> f'Hello {name}!'
# 'Hello Elizabeth!'

It is even possible to do inline arithmetic with it:

>>> a = 5
>>> b = 10
>>> f'Five plus ten is {a + b} and not {2 * (a + b)}.'
# 'Five plus ten is 15 and not 30.'

Multiline f-Strings

>>> name = 'Robert'
>>> messages = 12
>>> (
... f'Hi, {name}. '
... f'You have {messages} unread messages'
... )
# 'Hi, Robert. You have 12 unread messages'

The = specifier

This will print the expression and its value:

>>> from datetime import datetime
>>> now = datetime.now().strftime("%b/%d/%Y - %H:%M:%S")
>>> f'date and time: {now=}'
# "date and time: now='Nov/14/2022 - 20:50:01'"

Adding spaces or characters

>>> f"{name.upper() = :-^20}"
# 'name.upper() = -------ROBERT-------'
>>>
>>> f"{name.upper() = :^20}"
# 'name.upper() =        ROBERT       '
>>>
>>> f"{name.upper() = :20}"
# 'name.upper() = ROBERT              '

Formatting Digits

Adding thousands separator

>>> a = 10000000
>>> f"{a:,}"
# '10,000,000'

Rounding

>>> a = 3.1415926
>>> f"{a:.2f}"
# '3.14'

Showing as Percentage

>>> a = 0.816562
>>> f"{a:.2%}"
# '81.66%'

Number formatting table

Number Format Output description
3.1415926 {:.2f} 3.14 Format float 2 decimal places
3.1415926 {:+.2f} +3.14 Format float 2 decimal places with sign
-1 {:+.2f} -1.00 Format float 2 decimal places with sign
2.71828 {:.0f} 3 Format float with no decimal places
4 {:0>2d} 04 Pad number with zeros (left padding, width 2)
4 {:x<4d} 4xxx Pad number with x’s (right padding, width 4)
10 {:x<4d} 10xx Pad number with x’s (right padding, width 4)
1000000 {:,} 1,000,000 Number format with comma separator
0.35 {:.2%} 35.00% Format percentage
1000000000 {:.2e} 1.00e+09 Exponent notation
11 {:11d} 11 Right-aligned (default, width 10)
11 {:<11d} 11 Left-aligned (width 10)
11 {:^11d} 11 Center aligned (width 10)

Template Strings

A simpler and less powerful mechanism, but it is recommended when handling strings generated by users. Due to their reduced complexity, template strings are a safer choice.

>>> from string import Template
>>> name = 'Elizabeth'
>>> t = Template('Hey $name!')
>>> t.substitute(name=name)
# 'Hey Elizabeth!'

Python abs() built-in function Python aiter() built-in function Python all() built-in function Python any() built-in function Python ascii() built-in function Python bin() built-in function Python bool() built-in function Python breakpoint() built-in function Python bytearray() built-in function Python bytes() built-in function Python callable() built-in function Python chr() built-in function Python classmethod() built-in function Python compile() built-in function Python complex() built-in function Python delattr() built-in function Python dict() built-in function Python dir() built-in function Python divmod() built-in function Python enumerate() built-in function Python eval() built-in function Python exec() built-in function Python filter() built-in function Python float() built-in function Python format() built-in function Python frozenset() built-in function Python getattr() built-in function Python globals() built-in function Python hasattr() built-in function Python hash() built-in function Python help() built-in function Python hex() built-in function Python id() built-in function Python __import__() built-in function Python input() built-in function Python int() built-in function Python isinstance() built-in function Python issubclass() built-in function Python iter() built-in function Python len() built-in function Python list() built-in function Python locals() built-in function Python map() built-in function Python max() built-in function Python memoryview() built-in function Python min() built-in function Python next() built-in function Python object() built-in function Python oct() built-in function Python open() built-in function Python ord() built-in function Python pow() built-in function Python print() built-in function Python property() built-in function Python range() built-in function Python repr() built-in function Python reversed() built-in function Python round() built-in function Python set() built-in function Python setattr() built-in function Python slice() built-in function Python sorted() built-in function Python staticmethod() built-in function Python str() built-in function Python sum() built-in function Python super() built-in function Python tuple() built-in function Python type() built-in function Python vars() built-in function Python zip() built-in function