Python f-Strings
1f-Strings: overview
An f-string is a string literal starting with f whose {braces} hold Python expressions and optional format specs, so values are inserted into text and displayed exactly how you want.
Before this lesson: Python Variables, Python Strings
2f-Strings: diagram
3f-Strings: explained step by step
An f-string is a string that can hold Python expressions. Put the letter f in front of the opening quote, write any value or calculation inside {}, and Python replaces each pair of braces with the result. It is the cleanest way to mix text and values, and it is what you will use for almost every message, report and log line you print. If you are new to text values, start with Python strings and come back.
How f-string interpolation works
Everything inside the braces is a normal Python expression, evaluated at the moment the line runs. That means variables, arithmetic, function calls and method calls all work.
name = "Asha"
items = 3
price = 4.5
print(f"{name} bought {items} items")
print(f"Total: {items * price}")
print(f"Shouting: {name.upper()}, letters: {len(name)}")
print(f"Is it a bulk order? {items >= 10}")Unlike joining with +, you never convert numbers yourself: the f-string turns each result into text for you. That avoids the classic TypeError from adding a string to an int. For more text tools such as upper(), see Python string methods.
Format specifiers: control how a value looks
After the expression you can add a colon and a format spec. The expression says what to show, the spec says how. The most useful ones for numbers are:
price = 1234.5
ratio = 0.256
order_no = 42
print(f"{price:.2f}") # 2 decimal places
print(f"{price:,.2f}") # thousands separator
print(f"{ratio:.1%}") # percentage (multiplies by 100)
print(f"{order_no:05d}") # pad with zeros to 5 digits
print(f"{255:b} {255:x} {255:X} {255:o}") # binary, hex, octal
print(f"{12345.678:e}") # scientific notationRead .2f as "2 digits after the point, fixed notation". Rounding happens in the display only; the variable itself is unchanged. For rounding and other number tools see Python numbers.
Align and pad text with width
A number in the spec sets the width. Add <, > or ^ to left-align, right-align or centre inside that width, and put a character before the alignment symbol to use it as padding. This is how you build tidy columns without any extra libraries.
rows = [("Tea", 3.5), ("Coffee", 12), ("Cake", 4.25)]
for name, price in rows:
print(f"{name:<8}|{price:>8.2f}|")
print(f"{'TOTAL':*^17}")
print(f"{'left':-<10}{'right':->10}")Strings default to left alignment and numbers to right alignment, so you only need the symbol when you want the opposite.
Width and precision from variables
Format specs can contain their own braces, so the width does not have to be a fixed number. This is handy when column sizes depend on your data.
names = ["Asha", "Benjamin", "Li"]
width = max(len(n) for n in names) + 2
digits = 1
for n in names:
print(f"[{n:<{width}}]")
print(f"{3.14159:{width}.{digits}f}")Debug with the = specifier
Add = after an expression and the f-string prints the expression text, an equals sign and the value. It saves you from typing every label by hand while you debug.
total = 19.99
count = 3
print(f"{total=}")
print(f"{count * total=:.2f}")
print(f"{total = }")Quotes, braces and multi-line f-strings
Since Python 3.12 you may reuse the same quote type inside the braces, and backslashes are allowed there too. In older versions you had to use different quotes. Mixing quotes is still the more readable choice.
To print a literal brace, double it: {{ and }}. For a long message, wrap adjacent f-strings in parentheses; each piece needs its own f.
user = {"name": "Ben", "plan": "pro"}
print(f"{user['name']} is on {user["plan"]}")
print(f"Braces: {{plan}} means {user['plan']}")
message = (
f"Hello {user['name']},\n"
f"your plan is {user['plan']}."
)
print(message)Looking up dictionary values this way pairs well with Python dictionaries.
The !r conversion and formatting dates
!r shows the repr() of a value, which includes quotes and escape characters. It is the quickest way to spot stray spaces or newlines in text. Date and time objects accept strftime codes directly in the spec, so you do not need a separate call (see the datetime module).
from datetime import date
name = " Asha\n"
print(f"{name!r}")
launch = date(2026, 3, 9)
print(f"{launch:%d %B %Y}")
print(f"{launch:%A, %Y-%m-%d}")f-strings compared with format() and %
All three styles give the same result. f-strings win on readability because the value sits right where it appears in the text.
name, score = "Asha", 91.456
f"{name} scored {score:.1f}" # f-string (best)
"{} scored {:.1f}".format(name, score) # str.format()
"%s scored %.1f" % (name, score) # old % style
Use str.format() only when the template is stored separately from the values, such as text loaded from a file. If a spec fails with a ValueError (for example :.2f on a string), see Python ValueError, and for reading values from users see input and output.
Quick reference: f-Strings
- Python String Cheat Sheet: Methods and Formatting — Python strings are immutable text: use slicing to cut them, methods such as `upper()`, `strip()`, `split()` a…
- How to Convert an Int to a String in Python — Use `str(number)`, for example `str(42)` returns `"42"`. For formatting such as padding or commas, use an [f-…
- How to Pad a Number with Leading Zeros in Python — Use an f-string: `f"{7:03d}"` gives `'007'`. For text that is already a string, `"7".zfill(3)` gives the same…
- Python Tip Calculator Program (Split the Bill) — A tip calculator multiplies the bill by the tip percentage divided by 100, adds it to the bill, then divides …
- Python Program to Print a Multiplication Table — To print a multiplication table in Python, loop `i` from 1 to 10 with `range(1, 11)` and print `n * i` for ea…
- Python print() Function — `print(*objects, sep=' ', end='\n')` converts each value to text, joins them with `sep`, writes the result fo…
- Python String format() Method — `str.format()` fills `{}` placeholders in a string with the values you pass in, for example `"Hi {}".format("…
- Python round() Function — `round(number, ndigits=None)` rounds a number to `ndigits` decimal places, or to the nearest integer when `nd…
4f-Strings: syntax
f"text {expression}" # interpolate a value
f"{value:.2f}" # format spec after the colon
f"{value:>10}" f"{value:<10}" f"{value:^10}" # align in a width
f"{value:,}" f"{value:05d}" f"{value:.1%}" # separators, zero pad, percent
f"{value:{width}.{digits}f}" # width and precision from variables
f"{expression=}" # debug: prints expression=value
f"{value!r}" # use repr() of the value
f"{{literal braces}}" # doubled braces print { and }
5f-Strings: run the example
Press Run (or Ctrl + Enter). The output (step 6) appears directly below the code. Change anything and run it again.
customer = "Asha"
items = [("Notebook", 2, 3.5), ("Pen pack", 1, 4.25), ("Stapler", 1, 12.0)]
width = 10
print(f"Receipt for {customer}")
total = 0
for name, qty, price in items:
line_total = qty * price
total += line_total
print(f"{name:<{width}} x{qty} {line_total:>7.2f}")
tax = total * 0.08
print(f"{'Tax (8%)':<{width}} {tax:>7.2f}")
print(f"{'Total':<{width}} {total + tax:>7,.2f}")Expected outputReceipt for Asha
Notebook x2 7.00
Pen pack x1 4.25
Stapler x1 12.00
Tax (8%) 1.86
Total 25.11
7f-Strings: how the example works
Hover or tap a step to highlight its lines in the example above.
- Line 1-3A customer name, a list of (name, quantity, price) tuples and a column
widthof 10 stored in a variable. - Line 4-5The header line uses a plain f-string, then
totalstarts at 0. - Line 6-8The loop unpacks each tuple, computes
line_totaland adds it tototal. - Line 9
{name:<{width}}left-aligns the name in 10 characters, taking the width from the variable.{line_total:>7.2f}right-aligns the amount in 7 characters with two decimals, so the numbers line up. - Line 10
taxis 8% of the total, a float that has not been rounded yet. - Line 11A string literal can be formatted too. Quotes inside the braces differ from the outer quotes so the f-string stays readable.
- Line 12
{total + tax:>7,.2f}evaluates an expression, then right-aligns it with a thousands separator and two decimals.
8f-Strings: common mistakes
Forgetting the f prefix
✗ Wrong
name = "Asha"
print("Hello, {name}!")✓ Right
name = "Asha"
print(f"Hello, {name}!")Without the f before the opening quote Python treats the braces as ordinary characters. Add the prefix every time you want values inserted.
Using :.2f on a string
✗ Wrong
price = "19.5"
print(f"Price: {price:.2f}")✓ Right
price = "19.5"
print(f"Price: {float(price):.2f}")Number formats only work on numbers. A value that arrived as text (for example from input()) must be converted with float() first.
Using :d on a float
✗ Wrong
average = 82.5
print(f"Average: {average:d}")✓ Right
average = 82.5
print(f"Average: {average:.1f}")d means whole number. Use .0f to show a float without decimals, or .1f for one decimal, or round it yourself with round().
Empty braces in an f-string
✗ Wrong
print(f"Use {} to build a set")✓ Right
print(f"Use {{}} to build a set")Inside an f-string, {} must contain an expression. To print literal braces, double them: {{ and }}.
Putting the spec parts in the wrong order
✗ Wrong
total = 1234567.891
print(f"{total:.2,f}")✓ Right
total = 1234567.891
print(f"{total:,.2f}")The order is fixed: fill and alignment, width, thousands separator, .precision, then the type letter. The comma comes before .2f.
9f-Strings: exercises
Write your answer, then press Check. The checks run in your browser.
1. Make the greeting work
Fix the bug Easy ✓ Completedmake_greeting(name, unread) should return text like Hi Asha, you have 3 unread messages, but it returns the template unchanged. Fix the function.
def make_greeting(name, unread):
return "Hi {name}, you have {unread} unread messages"
print(make_greeting("Asha", 3))def make_greeting(name, unread):
return f"Hi {name}, you have {unread} unread messages"
print(make_greeting("Asha", 3))
2. Predict the formatted lines
Predict the output Easy ✓ CompletedRead the code and type exactly what it prints. Watch the spaces created by the widths. Then press Check.
price = 7.5
qty = 12
rate = 0.075
print(f"{price:.2f}")
print(f"[{qty:>5}]")
print(f"[{qty:<5}]")
print(f"{rate:.1%}")
print(f"{qty:03d}")
print(f"{price * qty=}")>5 pads on the left, <5 pads on the right. The last line prints the expression text, then the value.7.50
[ 12]
[12 ]
7.5%
012
price * qty=90.0
2 more exercises → 6 more examples
Questions learners ask
What is the difference between f-strings and str.format()?
Both use the same format specs, but an f-string evaluates the expressions in place: f"{name} is {age}". With str.format() you pass the values afterwards: "{} is {}".format(name, age). f-strings are shorter and easier to read; str.format() is only needed when the template is defined separately from the data.
How do I print a literal curly brace in an f-string?
Double it. f"{{name}}" prints {name}, and f"{{{name}}}" prints the value of name wrapped in braces. A single { always starts an expression.
How do I round to two decimals in an f-string?
Use the .2f spec: f"{price:.2f}" shows 3.14159 as 3.14. It rounds only the displayed text. If you need the rounded number itself for later calculations, use round(price, 2) instead.
Further reading
10Next lesson
Up nextPython Input and OutputInput and output is how a program talks to its user: input() reads a line the user types and returns it as a string, an…Related:
Python NumbersPython StringsPython String MethodsPython Input and Output
← Python String Methods · All Python Basics lessons · Practise in the IDE