Nested f-strings in Python

⏱️ 30 sec read 🐍 Python

A nested f-string puts an f-string (or a format spec computed at runtime) inside the curly braces of another f-string. It's the cleanest way to make precision, width, or fill characters dynamic — but quote rules and parser limits trip people up.

What Is a Nested f-string?

Two patterns show up under the "nested" label:

  1. Dynamic format spec — the part after the colon is computed: f"{value:.{n}f}"
  2. f-string inside an f-string expression — a literal f-string is one of the values: f"{f'inner {x}'}"

The first is by far the more useful pattern.

Dynamic Precision (the Most Common Use)

value = 3.14159265359

for n in range(1, 5):
    print(f"{value:.{n}f}")
# 3.1
# 3.14
# 3.142
# 3.1416

Dynamic Width and Padding

names = ["Alice", "Bob", "Charlie"]
width = max(len(n) for n in names)  # 7

for n in names:
    print(f"{n:<{width}} | done")
# Alice   | done
# Bob     | done
# Charlie | done

Dynamic Fill Character

fill = "*"
title = "REPORT"

f"{title:{fill}^20}"
# '*******REPORT*******'

Conditional Formatting Inside an f-string

Use a ternary expression — this isn't truly "nested," but it's the second-most-common reason people search for nested f-strings.

change = -0.042

f"{('▼' if change < 0 else '▲')} {abs(change):.1%}"
# '▼ 4.2%'

# Conditional precision:
n = 0
f"{value:.{2 if n == 0 else n}f}"  # '3.14' when n is 0

The Quote Rule (Python 3.11 and Earlier)

Before Python 3.12 you could not reuse the same quote character inside an f-string expression. This forces you to alternate quote styles:

# Python 3.11 — must use the OTHER quote inside braces:
data = {"name": "Alice"}
f"{data['name']}"      # OK — single quotes inside double-quoted f-string
# f"{data["name"]}"    # SyntaxError on 3.11 and earlier

# To nest f-strings, alternate:
inner = "world"
f"hello {f'{inner}!'}"  # 'hello world!'

Python 3.12+ Relaxed the Quote Rule (PEP 701)

# Python 3.12+ — same quotes are fine:
data = {"name": "Alice"}
f"{data["name"]}"   # 'Alice'  (would error pre-3.12)

# You can also nest f-strings with the same quotes:
f"hello {f"{inner}!"}"   # 'hello world!' on 3.12+

# And backslashes are allowed in expressions:
items = ["a", "b"]
f"{'\n'.join(items)}"   # OK on 3.12+, SyntaxError before

When to Use a Nested f-string vs format()

If the format spec is fully dynamic and reused, str.format() is often clearer:

spec = ".2f"
value = 3.14159

# Nested f-string:
f"{value:{spec}}"          # '3.14'

# format() — same result, sometimes cleaner:
"{:{}}".format(value, spec) # '3.14'

# format_map for many fields:
"{value:{spec}}".format_map({"value": value, "spec": spec})

Common Pitfalls

Pro Tip: Check your Python version with python --version. If you're on 3.12 or newer, the PEP 701 relaxation means most "nested f-string is a SyntaxError" advice on Stack Overflow is outdated.

← Back to Python Tips