It's nice to be able to include variables in template strings, but sometimes the variables need a bit of coercion to make them look the way we want them to in the output. For example, if we are performing calculations with currency, we may end up with a long decimal that we don't want to show up in our template:
subtotal = 12.32
tax = subtotal * 0.07
total = subtotal + tax
print(
"Sub: ${0} Tax: ${1} Total: ${total}".format(
subtotal, tax, total=total
)
)
If we run this formatting code, the output doesn't quite look like proper currency:
Sub: $12.32 Tax: $0.8624 Total: $13.182400000000001
To fix the preceding format string, we can include some additional information inside the curly braces to adjust the formatting of the parameters. There are tons of things we can customize, but the basic syntax inside the braces is the same. After providing the template value, we include a colon, and then some specific syntax for the formatting. Here's an improved version:
print(
"Sub: ${0:0.2f} Tax: ${1:0.2f} "
"Total: ${total:0.2f}".format(subtotal, tax, total=total)
)
The 0.2f format specifier after the colons basically says the following, from left to right:
- 0: for values lower than one, make sure a zero is displayed on the left-hand of the decimal point
- .: show a decimal point
- 2: show two places after the decimal
- f: format the input value as a float
We can also specify that each number should take up a particular number of characters on the screen by placing a value before the period. This can be useful for outputting tabular data, for example:
orders = [("burger", 2, 5), ("fries", 3.5, 1), ("cola", 1.75, 3)]
print("PRODUCT QUANTITY PRICE SUBTOTAL")
for product, price, quantity in orders:
subtotal = price * quantity
print(
f"{product:10s}{quantity: ^9d} "
f"${price: <8.2f}${subtotal: >7.2f}"
)
OK, that's a pretty scary-looking format string, so let's see how it works before we break it down into understandable parts:
PRODUCT QUANTITY PRICE SUBTOTAL burger 5 $2.00 $ 10.00 fries 1 $3.50 $ 3.50 cola 3 $1.75 $ 5.25
Nifty! So, how is this actually happening? We have four variables we are formatting, in each line of the for loop. The first variable is a string that is formatted with {product:10s}. This one is easier to read from right to left:
- s means it is a string variable.
- 10 means it should take up 10 characters. By default, with strings, if the string is shorter than the specified number of characters, it appends spaces to the right-hand side of the string to make it long enough (beware, however: if the original string is too long, it won't be truncated!).
- product:, of course, is the name of the variable or Python expression being formatted.
The formatter for the quantity value is{quantity: ^9d}. You can interpret this format from right to left as follows:
- d represents an integer value.
- 9 tells us the value should take up nine characters on the screen.
- ^ tells us that the number should be aligned in the center of this available padding; this makes the column look a bit more professional.
- (space) tells the formatter to use a space as the padding character. With integers, instead of spaces, the extra characters are zeros, by default.
- quantity: is the variable being formatted.
All these specifiers have to be in the right order, although all are optional: fill first, then align, then the size, and finally, the type.
We do similar things with the specifiers for price and subtotal. For price, we use {2:<8.2f}; and for subtotal, {3:>7.2f}. In both cases, we're specifying a space as the fill character, but we use the < and > symbols, respectively, to represent that the numbers should be aligned to the left or right within a minimum space of eight or seven characters. Further, each float should be formatted to two decimal places.
The type character for different types can affect formatting output as well. We've seen the s, d, and f types, for strings, integers, and floats. Most of the other format specifiers are alternative versions of these; for example, o represents octal format and X represents hexadecimal if formatting integers. The n type specifier can be useful for formatting integer separators in the current locale's format. For floating-point numbers, the % type will multiply by 100 and format a float as a percentage.