W3docs

Python f-Strings

Master Python f-strings: basic syntax, expressions, format specifiers, number formatting, dates, debugging with =, and common gotchas.

f-strings (formatted string literals) were introduced in Python 3.6 and are now the recommended way to embed values inside strings. They are faster than % formatting and str.format(), and far more readable because the variable name sits directly inside the string where it will appear.

This chapter covers:

  • Basic f-string syntax and how to embed variables
  • Evaluating expressions, method calls, and function calls inline
  • Format specifiers: alignment, width, precision, and number bases
  • Formatting dates and using the sign and zero-pad specifiers
  • The = debug specifier (Python 3.8+)
  • Multiline f-strings and reusable templates in functions
  • Common gotchas and how to avoid them

Related chapters: Format Strings · Python String Formatting · Python Strings · Python Dates · Python Regex

Basic Syntax

An f-string is any string literal that starts with the letter f (or F) immediately before the opening quote. Any Python expression you place inside curly braces {} is evaluated at runtime and its value is converted to a string and inserted into the result.

name = "Alice"
age = 30
print(f"My name is {name} and I am {age} years old.")
My name is Alice and I am 30 years old.

The f prefix works with single quotes, double quotes, and triple quotes:

language = "Python"
print(f'I love {language}!')          # single quotes
print(f"""I love {language}!""")      # triple quotes
I love Python!
I love Python!

Embedding Expressions

The {} placeholder accepts any valid Python expression — not just variable names. You can do arithmetic, comparisons, call methods, call functions, and access dictionary keys.

Arithmetic and comparisons

x = 10
y = 3
print(f"{x} divided by {y} is {x / y:.2f}")
print(f"The square of {x} is {x ** 2}")
print(f"Is {x} greater than {y}? {x > y}")
10 divided by 3 is 3.33
The square of 10 is 100
Is 10 greater than 3? True

Method calls

name = "alice smith"
print(f"Hello, {name.title()}!")
print(f"Uppercase: {name.upper()}")
Hello, Alice Smith!
Uppercase: ALICE SMITH

Function calls and built-ins

items = ["apples", "bananas", "cherries"]
print(f"You have {len(items)} items in the list.")
You have 3 items in the list.

Dictionary access

Use single quotes inside the braces to access dictionary keys (the outer string is double-quoted, so there is no conflict):

person = {"name": "Bob", "age": 25}
print(f"Name: {person['name']}, Age: {person['age']}")
Name: Bob, Age: 25

Conditional expressions

score = 72
print(f"Score: {score} => {'Pass' if score >= 60 else 'Fail'}")
Score: 72 => Pass

Format Specifiers

After the expression, add a colon : followed by a format spec to control how the value looks. The full mini-language syntax is:

{expression:[fill][align][sign][width][grouping][.precision][type]}

You do not need to use every part — combine only the pieces you need.

Alignment and width

Use < (left), > (right), or ^ (center) with a number to set the field width:

name = "Alice"
print(f"|{name:<10}|")   # left-align in a field of width 10
print(f"|{name:>10}|")   # right-align
print(f"|{name:^10}|")   # center
|Alice     |
|     Alice|
|  Alice   |

Specify a fill character before the alignment symbol to pad with something other than spaces:

print(f"|{'hello':*^15}|")  # fill with * and center
|*****hello*****|

Decimal precision

pi = 3.14159265
print(f"Pi is approximately {pi:.2f}")   # 2 decimal places
print(f"Pi is approximately {pi:.4f}")   # 4 decimal places
Pi is approximately 3.14
Pi is approximately 3.1416

Number formatting

price = 1234567.89
print(f"{price:,.2f}")   # comma as thousands separator
print(f"{price:e}")      # scientific notation
1,234,567.89
1.234568e+06

Show a value as a percentage directly — Python multiplies by 100 for you:

ratio = 0.853
print(f"{ratio:.1%}")
85.3%

Sign specifier

Use + to always show the sign, or a space to reserve a space for positive numbers (so columns line up with negative ones):

x = 42
y = -7
print(f"{x:+d}")    # +42
print(f"{y:+d}")    # -7
print(f"{x: d}")    # space before positive
print(f"{y: d}")    # -7
+42
-7
 42
-7

Zero-padding

Pad an integer to a fixed width with leading zeros using 0 before the width number:

print(f"{42:010d}")   # zero-pad to 10 digits
0000000042

Combine sign and zero-padding — the sign occupies the first position:

x = 42
print(f"{x:+010d}")   # +000000042
+000000042

Integer bases

x = 255
print(f"{x:d}")    # decimal   -> 255
print(f"{x:x}")    # hex lower -> ff
print(f"{x:X}")    # hex upper -> FF
print(f"{x:o}")    # octal     -> 377
print(f"{x:b}")    # binary    -> 11111111
255
ff
FF
377
11111111

Formatting Dates

When you put a datetime or date object inside an f-string, you can follow the colon with strftime format codes to control the output directly — no call to .strftime() needed:

from datetime import date
today = date(2024, 6, 19)
print(f"Today is {today:%B %d, %Y}")
print(f"ISO format: {today:%Y-%m-%d}")
Today is June 19, 2024
ISO format: 2024-06-19

See the Python Dates chapter for the full list of strftime format codes.

The = Debug Specifier (Python 3.8+)

Adding = after the expression name prints both the expression text and its value. This saves you from typing the variable name twice and is invaluable for quick debugging:

val = 42
result = val * 2
print(f"{val=}, {result=}")
val=42, result=84

String values get repr() treatment so you can see quotes:

name = "Alice"
print(f"{name=}")
name='Alice'

You can combine = with a format spec — put the spec after =:

pi = 3.14159265
print(f"{pi=:.3f}")
pi=3.142

Multiline f-Strings

For longer text you can span an f-string across lines. Two approaches work well.

Implicit string concatenation (no backslash needed inside parentheses):

name = "Alice"
age = 30
city = "London"
profile = (
    f"Name : {name}\n"
    f"Age  : {age}\n"
    f"City : {city}"
)
print(profile)
Name : Alice
Age  : 30
City : London

Triple-quoted f-string — the newlines are literal, so no \n is needed:

name = "Alice"
age = 30
report = f"""
Name : {name}
Age  : {age}
""".strip()
print(report)
Name : Alice
Age  : 30

Reusable Templates

f-strings are evaluated immediately, so you cannot store them as a template variable and fill them in later. Use a function instead:

def greet(name, role):
    return f"Hello, {name}! Your role is {role}."

print(greet("Alice", "admin"))
print(greet("Bob", "editor"))
Hello, Alice! Your role is admin.
Hello, Bob! Your role is editor.

If you genuinely need a deferred template, use str.format() — see Format Strings.

Literal Braces in the Output

To include a literal { or } character in the output, double it:

value = 42
print(f"The answer is {{value}} = {value}")
The answer is {value} = 42

Common Gotchas

Backslashes inside the expression (Python < 3.12)

Before Python 3.12, a backslash is not allowed inside the {} expression of an f-string. The workaround is to compute the value in a variable first:

items = ["a", "b", "c"]

# This raises SyntaxError on Python < 3.12:
# print(f"{'\n'.join(items)}")

# Workaround — pre-compute:
joined = "\n".join(items)
print(f"Items:\n{joined}")
Items:
a
b
c

Python 3.12 lifted this restriction, so backslashes are now valid inside f-string expressions.

Using the same quote type inside the expression

If the outer f-string uses double quotes, use single quotes for dictionary keys inside {}. If you need the same quote type, switch the outer quotes or use a variable:

person = {"name": "Bob"}

# Works — single quotes inside double-quoted f-string
print(f"Name: {person['name']}")

# Also works — pre-assign the key
key = "name"
print(f"Name: {person[key]}")
Name: Bob
Name: Bob

f-strings are not lazy

An f-string evaluates every expression at the moment the line runs. If you assign an f-string to a variable, it captures the current values — changing the variables later has no effect on the already-evaluated string:

x = 5
msg = f"x is {x}"
x = 99
print(msg)   # still shows 5, not 99
x is 5

Use a function (as shown above) when you need a template that evaluates later.

Quick Reference

SpecExampleOutput
:.2ff"{3.14159:.2f}"3.14
:,f"{1000000:,}"1,000,000
:.1%f"{0.853:.1%}"85.3%
:ef"{1234.5:e}"1.234500e+03
:10f"{'hi':10}"hi (left, width 10)
:<10f"{'hi':<10}"hi
:>10f"{'hi':>10}" hi
:^10f"{'hi':^10}" hi
:010df"{42:010d}"0000000042
:+df"{42:+d}"+42
:bf"{10:b}"1010
:xf"{255:x}"ff
=f"{val=}"val=42
:%Y-%m-%df"{date_obj:%Y-%m-%d}"2024-06-19

Practice

Practice
Which of the following statements about Python f-strings are correct?
Which of the following statements about Python f-strings are correct?
Was this page helpful?