ᚱᛗ
© 2022
Powered by Hugo

String Formatting

Table of Contents

Summary

A brief survey of Python’s string formatting methods. There are mainly three ways to format strings in Python. C-style formatting with % is the oldest, then came along str.format() with Python3, and finally f-strings with Python 3.6. F-string interpolation is arguably the most effective way to format strings in Python, but it’s good to know all the different possibilities.

1. C-style formatting (using the % operator)

This capability is modeled after C. It’s the original string-formatting method in Python. It works, but has a few drawbacks.

% operator with a tuple

tple = ("1st", "3rd", "2nd", "1st")
print("Return the %s, the %s, the %s, and finally the %s again" % tple)
# Return the 1st, the 3rd, the 2nd, and finally the 1st again

Disadvantages:

  • Both sides must remain in sync at all times. ie. order is “hardcoded” and has to be prioritized in case of edits.
  • Any one value has to be repeated (in the tuple) as many times as it is needed in the formatted string, creating unnecessary noise.

% operator with a dictionary

us_capitals = {"OR": "Salem", "WA": "Olympia", "ID": "Boise"}
formatted = (
    "Oregon's capital is %(OR)s, "
    "Washington's capital is %(WA)s, "
    "Idaho's capital is %(ID)s"
)
print(formatted % us_capitals)
# Oregon's capital is Salem, Washington's capital is Olympia, Idaho's capital is Boise

2. str.format()

This formatting method introduced curly braces, {}, as placeholders within strings. Same as with C-style formatting, the string to format and the contents to format it with live in separate places. Specifically, it follows this structure: "...{}...{}...".format(element1, element2); alternatively, the curly braces can hold the index of the element, to refer to it positionally, like so: "...{1}...{0}...".format(element1, element2) (where index 0 retrieves element1 and index 1 retrieves element2). In addition, this update included a powerful Format Specification Mini-Language with features to manipulate string/digits in terms of precision, alignment, width, capitalization, etc.

Basic demo

"{0}, {1}, {2}".format("a", "b", "c")
# 'a, b, c'
"{}, {}, {}".format("a", "b", "c")  # 3.1+ only
# 'a, b, c'
"{2}, {1}, {0}".format("a", "b", "c")
# 'c, b, a'
"{2}, {1}, {0}".format(*"abc")  # unpacking argument sequence
# 'c, b, a'
"{0}+{1}+{0}".format("abra", "cad")  # arguments' indices can be repeated
# 'abra+cad+abra'

Unpacking a dictionary’s values with str.format()

us_capitals = {"OR": "Salem", "WA": "Olympia", "ID": "Boise"}
formatted = (
    "Oregon's capital is {OR},"
    "Washington's capital is {WA},"
    "Idaho's capital is {ID}"
)
print(formatted.format(**us_capitals))
# Oregon's capital is Salem,Washington's capital is Olympia,Idaho's capital is Boise

Vis-a-vis C-style formatting, this method is more straightforward, having gotten rid of the need to add the % and the s. But it’s brittle in that it still depends on the ordering of the tuple’s elements (if used with a tuple). Using it with a dictionary makes it more robust.

3. f-string Interpolation (Python 3.6+)

With f-string interpolation variables or expressions are placed direcly inside curly braces (together with any extra formatting), which makes the whole formatted string self-contained. Thus making for a concise expression of somewhat terse elegance. The structure it follows is: f"...{<var>}...{<expr>}...".

Variables within {} placeholders

color = "blue"
weight = "2ton"
discount = 9.99
decimals = 2
formatted = f"The car is {color}, weighs {weight} and is for sale \
with a {discount:.{decimals}f}% discount"
print(formatted)
# The car is blue, weighs 2ton and is for sale with a 9.99% discount

Expressions within {} placeholders

# capitalize the brand and double the stock found in the garage
garage = [("tesla", 2), ("volvo", 1), ("bmw", 2)]

for i, (brand, qty) in enumerate(garage):
    row = f"row id:{i}, car maker:{brand.capitalize()}, stock:{2*qty}"
    print(row)

# row id:0, car maker:Tesla, stock:4
# row id:1, car maker:Volvo, stock:2
# row id:2, car maker:Bmw, stock:4

Extracting values from a dictionary

us_capitals = {"OR": "Salem", "WA": "Olympia", "ID": "Boise"}
formatted = (
    f"Oregon's capital is {us_capitals['OR']}, "
    f"Washington's capital is {us_capitals['WA']}, "
    f"Idaho's capital is {us_capitals['ID']} "
)
print(formatted)
# Oregon's capital is Salem, Washington's capital is Olympia, Idaho's capital is Boise