How to Format Numbers in Python f-Strings, Commas, Percents, Padding
Printing a number is easy. Printing it the way a person expects to read it, as $1,284,506 or 8.4% or INV-0007, takes one more step. Python's f-strings handle all of it with a short code after a colon inside the curly braces. The codes you will actually use are below, with every example run in Python 3 and its real output shown.
1. The basic f-string
The official tutorial describes formatted string literals, or f-strings, as strings prefixed with f in which you write expressions inside curly braces. Python evaluates each expression and inserts the result.
item = "notebook"
units = 3
price = 4.5
print(f"{units} x {item} = {units * price}")
3 x notebook = 13.5
Any expression works inside the braces, including math. To control how the value looks, add a colon and a format specifier after the expression: {value:spec}. The documentation calls the rules for these specifiers the "format specification mini-language."
2. Thousands separators
A comma in the specifier inserts a comma every three digits:
revenue = 1284506.5
print(f"{revenue:,}")
print(f"{revenue:,.2f}")
print(f"${revenue:,.0f}")
1,284,506.5
1,284,506.50
$1,284,506
,.2f combines two instructions: commas, and fixed-point with exactly two decimals. .0f rounds to a whole number. The dollar sign is not part of the specifier. It is ordinary text sitting just outside the braces.
3. Percentages
The % type, according to the documentation, multiplies the number by 100, shows it in fixed-point format, and adds a percent sign. That means you store the rate as a fraction and let the format do the conversion:
rate = 0.0837
print(f"{rate:.1%}")
print(f"{rate:%}")
print(f"{rate:.0%}")
8.4%
8.370000%
8%
Without a precision, you get six decimal places, which is rarely what you want. Always add .1% or similar.
4. Padding and alignment
A number after the colon sets a minimum width. The documentation lists the alignment symbols: < for left, > for right, and ^ for centered. Numbers are right-aligned by default, and most other values are left-aligned. You can put a fill character before the alignment symbol.
print(f"[{'left':<10}]")
print(f"[{'right':>10}]")
print(f"[{'center':^10}]")
print(f"[{42:10}]")
print(f"[{'Total':-^15}]")
[left ]
[ right]
[ center ]
[ 42]
[-----Total-----]
The square brackets are only there to make the spaces visible.
5. Zero padding for IDs and times
A 0 before the width pads numbers with zeros instead of spaces:
order = 7
print(f"INV-{order:04}")
print(f"{3:02}:{5:02}")
INV-0007
03:05
This keeps invoice numbers and clock times the same length, which also makes them sort correctly as text.
6. Showing a plus sign
For changes that can go up or down, + shows the sign on positive numbers too:
for change in (12.5, -3.4, 0.0):
print(f"{change:+.1f}%")
+12.5%
-3.4%
+0.0%
7. A small aligned table
Width, alignment, commas and decimals combine nicely for reports printed in a terminal:
rows = [("Paper", 4, 6.5), ("Toner", 1, 48.0), ("Desk lamp", 2, 129.99)]
print(f"{'Item':<10} {'Qty':>4} {'Total':>10}")
for name, qty, unit in rows:
print(f"{name:<10} {qty:>4} {qty * unit:>10,.2f}")
Item Qty Total
Paper 4 26.00
Toner 1 48.00
Desk lamp 2 259.98
Each column has a fixed width, so the numbers line up on the right no matter how many digits they have. The tutorial shows the same idea with a phone list, using {name:10} and {phone:10d}.
8. The = shortcut for debugging
The tutorial describes an = specifier that prints the expression's text, an equals sign, and its value. It saves typing labels while you hunt for a bug:
subtotal = 19.5
tax_rate = 0.08
print(f"{subtotal=}")
print(f"{subtotal * tax_rate=:.2f}")
subtotal=19.5
subtotal * tax_rate=1.56
You can still add a format after the =, as the second line shows.
9. Two things that surprise beginners
Formatting a string as a number fails. Values read from files or input() are strings, even when they look like numbers:
total = "1,250"
print(f"{total:,.2f}")
ValueError: Unknown format code 'f' for object of type 'str'
Convert to a number first. For "1,250" that means removing the comma and calling float().
Rounding a half is not always up. The documentation for round() warns that round(2.675, 2) gives 2.67, not 2.68, because most decimal fractions cannot be stored exactly as a float. Formatting shows the same thing:
print(f"{2.675:.2f}")
2.67
For everyday display this rarely matters. For money calculations where every cent must follow a rule, look into the decimal module from the standard library.
10. Key takeaways
- Put a format specifier after a colon inside the braces:
{value:spec}. ,adds thousands separators, and.2ffixes two decimal places; combine them as,.2f..1%multiplies by 100 and adds a percent sign, so store rates as fractions.- A width plus
<,>or^aligns columns; a leading0pads numbers with zeros. {x=}prints the expression and its value, which is handy for debugging.