Build readable output with f-strings and format specifications: fixed decimals, thousands separators, percentages, padding and aligned columns.
About 35 minBeginner4 exercisesFree
You will be able to
Put variables and expressions inside text with f-strings
Control decimals, thousands separators and percentages with a format specification
Pad values to a fixed width and align them left, right or centre
Build a neatly aligned receipt or report
Compare these two lines from a sales report:
Revenue for Desk lamp : 48737.5 SAR
Revenue: 48,737.50 SAR
The second one is what a manager wants to read: two decimals, a thousands separator, no stray spaces. Producing it with print() and commas, or by gluing strings with + and str(), gets messy fast. f-strings let you write the line exactly as it should look and drop values into it, with precise control over how each value is shown.
The basics
Put an f right before the opening quote. Inside the string, anything in curly braces { } — a replacement field — is evaluated as Python and its value is inserted:
A replacement field can hold any expression, not only a variable name: {items * 2}, {customer.upper()}, {len(customer)}. Numbers are converted to text for you, so no str() is needed.
Variables and expressions inside an f-string
customer ="noura al-harbi"
unit_price =12.5
quantity =4print(f"Customer: {customer.title()}")print(f"{quantity} x {unit_price} = {quantity * unit_price}")print(f"Name has {len(customer)} characters")
Try it: Remove the f before one of the strings and run it. What gets printed instead?
Format specifications
After the expression you can add a colon and a format specification that controls how the value looks: {value:spec}. You met :.2f in Float precision and rounding. Here are the most useful pieces:
spec
meaning
example
result
.2f
2 decimal places
f"{3.14159:.2f}"
3.14
,
thousands separator
f"{1250000:,}"
1,250,000
,.2f
both together
f"{48737.5:,.2f}"
48,737.50
.1%
percentage (×100, adds %)
f"{0.175:.1%}"
17.5%
05d
integer, zero-padded to width 5
f"{42:05d}"
00042
Order matters inside a spec: separator before the dot, type letter last (,.2f, not .2f,).
Try it: Change growth to 0.5 and order_id to 1234567. What happens when a number is wider than its width?
Width and alignment
A number at the start of the spec sets a minimum width: the value is padded with spaces until it is that wide. An alignment sign chooses where the padding goes:
< left-align (the default for text)
> right-align (the default for numbers)
^ centre
You can put a fill character before the sign, and combine width with the other parts: {price:>8.2f} means "right-align in 8 characters, 2 decimals". A value that is already wider than the width is never cut — it pushes the rest of the line over.
An aligned receipt: left-aligned names, right-aligned prices
print(f"{'Riyadh Books':^20}")print("="*20)print(f"{'Notebook':<12}{8.5:>8.2f}")print(f"{'Pen set':<12}{24:>8.2f}")print(f"{'Atlas':<12}{115.75:>8.2f}")print("-"*20)print(f"{'Total':<12}{8.5+24+115.75:>8.2f}")print(f"{' Thank you ':*^20}")
Try it: Change the widths 12 and 8 to 14 and 10, and the separator lines to 24 characters, so everything still lines up.
Every row uses the same widths (12 for the name, 8 for the price), so the columns line up no matter how long each name or price is. That's the whole trick to tabular output.
One more handy feature for checking your work: f"{subtotal=}" prints the expression and its value, like subtotal=148.25. It's useful while you debug.
Guided practice · ●difficulty 1 of 5 · about 4 min
Format a salary statement
An HR system prints a short salary statement. Read an annual salary as a whole number with int(input()) (no prompt text — the tests type the values for you). Work out the monthly salary (annual ÷ 12) and print two lines.
For 145000:
Annual salary: 145,000 SAR
Monthly: 12,083.33 SAR
The annual figure has a thousands separator and no decimals; the monthly figure has a separator and exactly two decimals.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Challenge · ●●●difficulty 3 of 5 · about 10 min
Print an aligned café receipt
A café wants receipts with neat columns. Read three items: for each one, a name and then a price, so six input() calls in total (no prompt text). Store the sum of the prices in total.
Print a receipt where every row is 20 characters wide: the name left-aligned in 12 characters, the price right-aligned in 8 characters with 2 decimals. For the inputs Coffee, 14.5, Croissant, 9.75, Orange juice, 21:
Item Price
Coffee 14.50
Croissant 9.75
Orange juice 21.00
--------------------
Total 45.25
The header uses the same widths (Item left in 12, Price right in 8), and the dashed line is 20 dashes.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Edge cases · ●●difficulty 2 of 5 · about 6 min
Zero-padded invoice numbers and percentages
An accounting system prints invoice labels. Read an invoice number (an int) and a discount rate given as a fraction (a float, e.g. 0.15 for 15%) with two input() calls (no prompt text). Print:
the invoice number padded with zeros to at least 5 digits, after Invoice #,
the discount as a percentage with one decimal place.
For 42 and 0.15:
Invoice #00042
Discount: 15.0%
Think about invoice numbers that already have more than five digits, and orders with no discount.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Debugging · ●●difficulty 2 of 5 · about 6 min
Fix the sales report
A furniture shop's report program reads a product name, units sold and revenue (three input() calls, no prompt text). For Desk lamp, 1250 and 48737.5 it should print:
Product: Desk lamp
Units sold: 1,250
Revenue: 48,737.50 SAR
Instead the first line shows curly braces and a variable name, and the revenue appears as 48737.500000 with no separator. Fix the program.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Summary
An f-string (f"...") evaluates each {expression} and inserts its value as text.
A format specification after a colon controls display: .2f for decimals, , for separators, .1% for percentages, 05d for zero padding.
A number in the spec is a minimum width; <, > and ^ choose left, right or centre alignment, with an optional fill character.
Aligned tables come from using the same widths on every row.