Python f-strings explained: format numbers and text
Python f-strings put values straight into text. Learn decimals, thousands separators, percentages, column alignment and the {value=} debug trick.

How do you print a price with two decimals, line up a column of numbers, or show a percentage in Python without a pile of str() calls?
Short answer: use an f-string. Put f before the quotes, then any variable or expression inside {}. Add a colon and a format spec to control how it looks: f"{price:.2f}" gives two decimals, f"{name:<10}" pads to ten characters, and f"{rate:.1%}" shows a percentage.
By the end of this post you will drop values into text, format numbers for people to read, line up a small table, and debug with one handy shortcut. If strings are still new, start with F Strings (opens in a new tab).
The basics: put values inside {}
name = "Ana"
tickets = 3
print(f"{name} bought {tickets} tickets") # Ana bought 3 ticketsThe f before the opening quote turns the string into an f-string. Anything inside {} is evaluated and turned into text. That includes expressions, not just variable names:
print(f"{name.upper()} has {len(name)} letters") # ANA has 3 letters
print(f"Total: {tickets * 12}") # Total: 36
print(f"{'sold out' if tickets > 2 else 'available'}") # sold outNo str() calls, no + between pieces, and no counting %s placeholders. That's why f-strings replaced "%s" % value and .format() in most modern Python code.
Format numbers with a colon
After the value, add : and a format spec. These are the ones you'll use most:
price = 1234.5
rate = 0.075
score = 7
print(f"{price:.2f}") # 1234.50 two decimal places
print(f"{price:,.2f}") # 1,234.50 thousands separator
print(f"{rate:.1%}") # 7.5% multiplies by 100 and adds %
print(f"{score:03d}") # 007 pad with zeros to 3 digits
print(f"{1234567:_}") # 1_234_567 underscores instead of commasRead .2f as "fixed-point, 2 digits after the dot". The , goes before the dot. And % does the multiplying for you, so pass 0.075, not 7.5. Formatting Numbers (opens in a new tab) practices each of these.
One rounding surprise to know about: Python rounds halves to the nearest even digit, so f"{2.5:.0f}" is "2" and f"{3.5:.0f}" is "4". Some decimals also can't be stored exactly, which can tip a value you'd expect to round up. For money, that's a reason to keep amounts as whole cents, or use the decimal module, and only format at the end.
Line things up with width and alignment
A number before the format type sets a minimum width. <, > and ^ choose left, right or centre alignment:
name = "Ana"
print(f"[{name:<8}]") # [Ana ]
print(f"[{name:>8}]") # [ Ana]
print(f"[{name:^8}]") # [ Ana ]
print(f"[{name:*^8}]") # [**Ana***] fill character goes firstPut width and decimals together and you can print a tidy receipt:
items = [("Popcorn", 4.5), ("Soda", 2.25), ("Nachos", 6)]
for item, cost in items:
print(f"{item:<10}{cost:>8.2f}")Popcorn 4.50
Soda 2.25
Nachos 6.00
{item:<10} pads each name to ten characters, so every price starts in the same column. {cost:>8.2f} right-aligns each price in eight characters with two decimals, so the dots line up. This is where learners in Width And Alignment (opens in a new tab) get stuck most, and the trick is to read a spec left to right: fill, alignment, width, then decimals and type.
The width can come from a variable too, with nested braces: f"{price:>{width}.1f}".
Debug with {value=}
Add = after an expression and the f-string prints both the expression and its value:
score = 7
name = "Ana"
print(f"{score=}") # score=7
print(f"{name=}") # name='Ana'It's the quickest way to check what a variable holds while you work, and you can still add a format spec after it: f"{price=:.1f}".
Other handy formats
from datetime import date
today = date(2026, 10, 21)
print(f"{today:%d %b %Y}") # 21 Oct 2026
print(f"{255:x}") # ff hexadecimal
print(f"{12:b}") # 1100 binary
print(f"{3:+d}") # +3 always show the sign
print(f"{{braces}}") # {braces}Dates accept the same codes as strftime(), right inside the braces. And to print a literal { or }, double it.
Common mistakes
- Forgetting the
f."Total: {total}"prints the braces as they are. Python won't warn you, so check the output. - Formatting too early.
f"{price:.2f}"returns a string. Do your math on the number, then format it once, when you print or display it. - Passing a percentage already multiplied.
f"{7.5:.1%}"gives750.0%. Pass the fraction,0.075. - Mixing up width and decimals. In
{cost:8.2f},8is the total width, including the dot and decimals, and2is the number of decimals. - Reusing the same quotes inside.
f"{d["name"]}"only works on Python 3.12 and later. For code that runs on older versions, use the other quote type inside:f"{d['name']}".
Quick recap
f"...{value}..."drops any variable or expression into text.- After a colon,
.2fsets decimals,,adds separators and%shows a percentage. <,>and^with a width line values up into columns.{value=}prints the name and the value, which is great for debugging.- Format at the end. Keep the number as a number until you display it.
Frequently asked questions
What is an f-string in Python?
A string literal with f in front, like f"Hi {name}". Python replaces each {} with the value of the expression inside it. F-strings have been in Python since version 3.6.
How do I format a number to 2 decimal places?
Use :.2f inside the braces: f"{price:.2f}". Add a comma for thousands separators: f"{price:,.2f}".
What's the difference between f-strings and format()?
They use the same format specs, so f"{x:.2f}" and "{:.2f}".format(x) give the same result. F-strings are shorter and put each value right where it appears, which makes them easier to read.
Can I use an f-string with a dictionary?
Yes. Use the other quote type for the key: f"{player['name']} scored {player['score']}". On Python 3.12 and later, the same quote type works too.
Practice
Try each one in your browser, with nothing to install: Formatting Numbers (opens in a new tab), then Width And Alignment (opens in a new tab), then put both to work in the Cinema Tickets (opens in a new tab) project. For quick reps on the loops that usually surround a formatted table, try the Python Loops challenges.
Where to go next
Formatting sits in the input and output module of Intermediate Python (opens in a new tab). If you're newer to Python, Python for Beginners (opens in a new tab) covers f-strings early on, and our 30-day Python roadmap shows what comes after.







