Menu

Python f-Strings: Formatting, Expressions, and Number Specifiers

A practical guide to Python f-strings — embedding variables and expressions, formatting numbers and dates, and when to reach for the older format styles.

The Format You'll Actually Use

f-strings are the default way modern Python code embeds values into text. Put an f in front of the opening quote, and anything inside {...} becomes a live expression:

main.py
Output
Click Run to see the output here.

Three things to notice. The f prefix turns the whole literal into a template. The braces are the substitution points. And the expression inside the braces is evaluated at the moment print runs, not when the string was written.

You'll write f-strings far more often than any other formatting style. They're shorter than "Hello, " + name + ".", clearer than "Hello, %s." % name, and more flexible than .format().

Anything That Evaluates Can Go Inside

The braces aren't restricted to variable names. Any Python expression is fair game:

main.py
Output
Click Run to see the output here.

Method calls, indexing, arithmetic, conditional expressions — all fine. The one rule: keep what's between the braces short. If you're writing a three-line calculation inside a placeholder, compute it into a named variable first and drop the name in instead.

Formatting Numbers

A colon after the expression opens a format spec — a mini-language for controlling how the value is displayed:

main.py
Output
Click Run to see the output here.

A quick guide to what each piece does:

  • .2f — float, two digits after the point. Rounds to display.
  • , — comma as a thousands separator. Works for int and float.
  • .1% — multiply by 100 and append %. Great for ratios and rates.
  • .2e — scientific notation with two decimal digits.

You can combine them. f"{total:,.2f}" gives "1,234.57".

Padding, Width, and Alignment

For lining up columns of output:

main.py
Output
Click Run to see the output here.

<10 means "left-align, padded to at least 10 characters." >5 means "right-align, padded to 5." You can also use ^ for centered.

Pad with something other than spaces by putting the fill character before the alignment flag:

main.py
Output
Click Run to see the output here.

Formatting Dates

The same {value:spec} syntax works for datetime objects:

main.py
Output
Click Run to see the output here.

The spec after the colon is a strftime format string. Every %-code available to strftime works here — we'll cover those in detail on the datetime page.

The = Trick for Debugging

One of the most useful niche features: put = after the expression and Python prints both the expression source and its value:

main.py
Output
Click Run to see the output here.

You get count=7, price=19.99, count * price=139.93. That's a full print("count =", count) in three characters. Worth remembering the next time you're debugging and want to dump a few values.

Escaping Braces

If you need a literal { or } in the output, double them:

main.py
Output
Click Run to see the output here.

Single braces open an expression; {{ and }} stand in for { and } in the output.

Multi-Line f-Strings

f-strings play nicely with triple quotes, which helps when you're building small templates inline:

main.py
Output
Click Run to see the output here.

You can break a long f-string across several adjacent string literals too — Python concatenates them automatically:

main.py
Output
Click Run to see the output here.

When the Old Styles Still Show Up

You'll bump into two older formatting styles in existing code:

main.py
Output
Click Run to see the output here.

All three produce the same output. f-strings win on readability in nine cases out of ten. Reach for .format() when you need to build a template once and apply it many times; use % only when you're maintaining older code that already uses it.

What They're Not Good For

Two situations call for a different tool.

Building SQL queries. Never interpolate user input into an SQL string with an f-string. Use your database library's parameterized queries. An f-string there is how SQL injection happens.

Building translated UI text. If your app supports multiple languages, you want a template that external translation tools can pick up — usually gettext's _(...) or a framework-specific helper. An f-string embeds the structure in the source code, which makes translation much harder.

For everything else — logs, console output, URL construction, building config strings, formatting numbers for display — f-strings are the right answer.

Next: Numbers and Booleans

f-strings get a lot of mileage formatting numbers, so it's worth knowing the numeric types a little more deeply. That's next.

Frequently Asked Questions

What is an f-string in Python?

An f-string is a string literal prefixed with f, where anything inside {...} is replaced at runtime with the value of the expression. f"Hello, {name}" plugs the current value of name into the string.

When were f-strings added to Python?

Python 3.6. Every modern Python version supports them, so you can use f-strings anywhere you're writing Python 3 code today. Older formatting styles (% and .format()) still work but read less cleanly for most cases.

How do I format a number to 2 decimal places in Python?

Use a format spec after a colon inside the braces: f"{price:.2f}". The .2f means 'float with two digits after the decimal point.' It rounds the displayed value; the original number isn't changed.

Can I put any expression inside an f-string?

Yes — arithmetic, method calls, function calls, conditional expressions. f"{name.upper()}" and f"{price * 1.2:.2f}" both work. Keep expressions short; if the code inside the braces gets hairy, compute it into a variable first.

Learn to code with Coddy

GET STARTED