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 quotesI 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? TrueMethod calls
name = "alice smith"
print(f"Hello, {name.title()}!")
print(f"Uppercase: {name.upper()}")Hello, Alice Smith!
Uppercase: ALICE SMITHFunction 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: 25Conditional expressions
score = 72
print(f"Score: {score} => {'Pass' if score >= 60 else 'Fail'}")Score: 72 => PassFormat 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 placesPi is approximately 3.14
Pi is approximately 3.1416Number formatting
price = 1234567.89
print(f"{price:,.2f}") # comma as thousands separator
print(f"{price:e}") # scientific notation1,234,567.89
1.234568e+06Show 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
-7Zero-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 digits0000000042Combine sign and zero-padding — the sign occupies the first position:
x = 42
print(f"{x:+010d}") # +000000042+000000042Integer 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 -> 11111111255
ff
FF
377
11111111Formatting 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-19See 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=84String 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.142Multiline 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 : LondonTriple-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 : 30Reusable 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} = 42Common 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
cPython 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: Bobf-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 99x is 5Use a function (as shown above) when you need a template that evaluates later.
Quick Reference
| Spec | Example | Output |
|---|---|---|
:.2f | f"{3.14159:.2f}" | 3.14 |
:, | f"{1000000:,}" | 1,000,000 |
:.1% | f"{0.853:.1%}" | 85.3% |
:e | f"{1234.5:e}" | 1.234500e+03 |
:10 | f"{'hi':10}" | hi (left, width 10) |
:<10 | f"{'hi':<10}" | hi |
:>10 | f"{'hi':>10}" | hi |
:^10 | f"{'hi':^10}" | hi |
:010d | f"{42:010d}" | 0000000042 |
:+d | f"{42:+d}" | +42 |
:b | f"{10:b}" | 1010 |
:x | f"{255:x}" | ff |
= | f"{val=}" | val=42 |
:%Y-%m-%d | f"{date_obj:%Y-%m-%d}" | 2024-06-19 |