f-strings
Build text with values mixed in
In this lesson
Explain it like I’m 5
An f-string is a sentence with blanks you fill in. You write the sentence once and drop your variables into the blanks, and Python builds the finished text for you.
The basic syntax
Put an f before the opening quote, then write {variable} wherever you want a value: f"Hello, {name}!". Python replaces each {...} with the value inside. This reads far better than gluing pieces together with +, and it handles non-string values automatically.
name = "Ada"
messages = 3
print(f"Hi {name}, you have {messages} new messages.")
Hi Ada, you have 3 new messages.
Expressions inside the braces
The braces can hold any expression, not just a variable: f"Total: {price * quantity}" or f"{name.upper()}". Python evaluates what’s inside and inserts the result. Keep these expressions simple, though — heavy logic inside an f-string hurts readability.
price = 4
quantity = 3
name = "ada"
print(f"Total: {price * quantity}")
print(f"Shouting: {name.upper()}")
Total: 12 Shouting: ADA
Formatting numbers and dates
After a colon inside the braces you can add a format spec. f"{price:.2f}" shows two decimal places; f"{total:,}" adds thousands separators; f"{ratio:.0%}" shows a percentage. These specs are perfect for money, measurements, and tidy reports.
Dates and times use the very same colon, followed by a strftime pattern instead of a number spec: f"{when:%Y-%m-%d}" gives an ISO date, f"{when:%H:%M}" a 24-hour time, and codes like %A (weekday) and %B (month name) build a friendly, human-readable date. The % letters are placeholders Python fills in from the datetime value.
price = 12.5
big = 1234567
ratio = 0.875
print(f"Price: ${price:.2f}")
print(f"Views: {big:,}")
print(f"Score: {ratio:.0%}")
Price: $12.50 Views: 1,234,567 Score: 88%
from datetime import datetime
when = datetime(2026, 3, 9, 14, 5)
print(f"ISO date: {when:%Y-%m-%d}")
print(f"24-hour time: {when:%H:%M}")
print(f"Friendly: {when:%A, %d %B %Y}")
ISO date: 2026-03-09 24-hour time: 14:05 Friendly: Monday, 09 March 2026
Use an f-string to print a one-line receipt: the item, the quantity, and the total cost formatted to 2 decimals.
item = "coffee"
quantity = 3
unit_price = 2.5
# print: 3 x coffee = $7.50
print()
Compute the total inside the braces and format it: {quantity * unit_price:.2f}.
item = "coffee"
quantity = 3
unit_price = 2.5
print(f"{quantity} x {item} = ${quantity * unit_price:.2f}")
3 x coffee = $7.50
Why f-strings over the old ways
Older code uses + concatenation (which fails on numbers without str()) or %/.format(). f-strings are shorter, put the value right where it appears in the text, and convert types for you. Unless you’re supporting very old Python, f-strings are the right default.
Alignment, padding, and the {x=} debug trick
Format specs handle layout too, not just decimals. After the colon you can set a width and alignment: {name:<10} left-aligns in 10 columns, {n:>6} right-aligns, and {n:^7} centres. That’s how you line up tidy columns of text and numbers.
And a genuinely handy debugging shortcut: f"{value=}" prints both the expression and its value — total=42 — so you don’t have to type the label yourself. It pairs nicely with the print-based debugging habit.
for item, price in [("Coffee", 3), ("Tea", 2.5)]:
print(f"{item:<8}{price:>6.2f}")
total = 42
print(f"{total=}")
Coffee 3.00 Tea 2.50 total=42
Common mistake: Forgetting the leading f
Without the f prefix, Python sees an ordinary string and prints the braces literally instead of substituting values.
Always put f immediately before the opening quote: f"...".
Common mistake: Using the same quote type inside the braces
Inside an f-string delimited by double quotes, using double quotes again inside the braces ends the string early.
Use the other quote style inside: f"{d['key']}", or switch the outer quotes.
What makes a string an f-string?
The f prefix activates the {...} substitution; without it the braces are literal.
What does f"{price:.2f}" do when price is 5?
:.2f formats the number with exactly two decimals, so 5 becomes 5.00.
Mini exercise (easy)
Given name = "Sam" and score = 0.875, print Sam scored 88% using an f-string with percentage formatting.
Do it here. Finish the code below and press Run to try your answer right in the browser — no setup needed.
name = "Sam"
score = 0.875
line = "" # TODO: f-string -> "Sam scored 88%"
print(line)
Percentage format is :.0%, which also multiplies by 100: {score:.0%}.
name = "Sam"
score = 0.875
line = f"{name} scored {score:.0%}"
print(line)
__no_output_bypass__ = True
import ast as _ast
assert any(isinstance(n, _ast.JoinedStr) for n in _ast.walk(_ast.parse(__user_code__))), "use an f-string (f\"...\") — don't hardcode the answer"
__no_output_bypass__ = False
assert line == "Sam scored 88%", "use :.0% formatting inside the f-string: {score:.0%}"
print("✓ Formatted!")