Friday, January 24, 2025

Python formatting

Python string formatters

I use Python and I output data for reports, which means I need to format strings precisely. I find the string formatters hard to use and resources to explain them are scattered over the web. So I decided to write up my own guide to using formatters. This is mainly for me to have a 'cheat sheet', but I hope you find some use for it too. Of course, I've liberally copied and pointed to the Python documentation.

(This is a Python blog post! Image source: Wikimedia Commons. License: Creative Commons.)

Overview

Python string formatters have this general form:

{identifier : format specifier}

The term identifier is something I made up for easier reference.

Identifiers

The identifier ties the string format to the code in the format statement. Identifiers can be positional (numbered) or named. Numbered identifiers must start from zero and should increment by 1, but you can re-use identifiers like this:

'Today is {0}-{1}-{2} the year is {0}'.format(2020, 10, 22)

You can also use names as identifiers:

'Today is {year}-{month}-{day} the year is {year}'.format(year=2020, month=10, day=22)

and relatedly, you can use a dict:

'Today is {year}-{month}-{day} the year is {year}'.format(**date)

You can read more clever uses of identifiers here: https://docs.python.org/3.4/library/string.html#format-string-syntax

Format specifiers

There's an entire format specifier mini language: https://docs.python.org/3.4/library/string.html#formatspec

The general form is:
[[fill]align][sign][#][0][width][,][.precision][type]
  • fill is the character to use to fill padded spaces
  • align is the instruction on how to align the string (left, center, right)
  • sign, the + or - sign, only makes sense for numbers
  • # indicates an alternate form for conversion
  • 0 - used for sign aware zero padding for numbers
  • width - the width in characters of the field
  • , - use of the thousand separator
  • .precision - the number of digits after the decimal place
  • type - one of these special types: "b", "c", "d", "e", "E", "f", "F", "g", "G", "n", "o", "s", "x", "X", "%"
Type Meaning
's' String format. This is the default type for strings and may be omitted.
None The same as 's'.
Type Meaning
'b' Binary format. Outputs the number in base 2.
'c' Character. Converts the integer to the corresponding unicode character before printing.
'd' Decimal Integer. Outputs the number in base 10.
'o' Octal format. Outputs the number in base 8.
'x' Hex format. Outputs the number in base 16, using lower- case letters for the digits above 9.
'X' Hex format. Outputs the number in base 16, using upper- case letters for the digits above 9.
'n' Number. This is the same as 'd', except that it uses the current locale setting to insert the appropriate number separator characters.
None The same as 'd'.
Type Meaning
'e' Exponent notation. Prints the number in scientific notation using the letter ‘e’ to indicate the exponent. The default precision is 6.
'E' Exponent notation. Same as 'e' except it uses an upper case ‘E’ as the separator character.
'f' Fixed point. Displays the number as a fixed-point number. The default precision is 6.
'F' Fixed point. Same as 'f', but converts nan to NAN and inf to INF.
'g'

General format. For a given precision p >= 1, this rounds the number to p significant digits and then formats the result in either fixed-point format or in scientific notation, depending on its magnitude.

The precise rules are as follows: suppose that the result formatted with presentation type 'e' and precision p-1 would have exponent exp. Then if -4 <= exp < p, the number is formatted with presentation type 'f' and precision p-1-exp. Otherwise, the number is formatted with presentation type 'e' and precision p-1. In both cases insignificant trailing zeros are removed from the significand, and the decimal point is also removed if there are no remaining digits following it.

Positive and negative infinity, positive and negative zero, and nans, are formatted as inf-inf0-0 and nan respectively, regardless of the precision.

A precision of 0 is treated as equivalent to a precision of 1. The default precision is 6.

'G' General format. Same as 'g' except switches to 'E' if the number gets too large. The representations of infinity and NaN are uppercased, too.
'n' Number. This is the same as 'g', except that it uses the current locale setting to insert the appropriate number separator characters.
'%' Percentage. Multiplies the number by 100 and displays in fixed ('f') format, followed by a percent sign.
None Similar to 'g', except that fixed-point notation, when used, has at least one digit past the decimal point. The default precision is as high as needed to represent the particular value. The overall effect is to match the output of str() as altered by the other format modifiers.

f-strings

These are a way of simplifying Python string formatting and really should be your preferred way of outputting strings. Very usefully, they allow you to embed expressions. Here are a couple of examples.

number = 10
print(f"The number is {number}")
10
print(f"The expression is {number + 100}")
110

Examples

'{:<30}'.format('left aligned')
'{:*^30}'.format('centered')
"int: {0:d};  hex: {0:x};  oct: {0:o};  bin: {0:b}".format(42)
'{:,}'.format(1234567890)
'Correct answers: {:.2%}'.format(points/total)