Python f-strings Deep Dive
f-strings (formatted string literals, PEP 498, Python 3.6+) are the fastest and most readable way to build strings. Prefix a string with f and embed expressions in {}. This page goes deep into formatting; for the broader picture of %, .format(), and templates, see String Formatting.
name = "Ada"
age = 36
print(f"{name} is {age}") # Ada is 36
print(f"Next year: {age + 1}") # Next year: 37 (any expression works)Expressions, not just variables
Section titled “Expressions, not just variables”Anything that evaluates to a value can go inside the braces — arithmetic, method calls, indexing, conditionals.
items = ["a", "b", "c"]
print(f"{len(items)} items") # 3 items
print(f"upper: {'hi'.upper()}") # upper: HI
print(f"first: {items[0]}") # first: a
print(f"{'even' if 4 % 2 == 0 else 'odd'}") # evenThe format spec mini-language
Section titled “The format spec mini-language”After a colon inside the braces comes a format spec that controls width, alignment, precision, and type. The general shape is:
{value:[fill][align][sign][width][,][.precision][type]}Number precision
Section titled “Number precision”pi = 3.14159265
print(f"{pi:.2f}") # 3.14 (2 decimal places)
print(f"{pi:.0f}") # 3 (no decimals)
print(f"{1/3:.4f}") # 0.3333Width, alignment, and fill
Section titled “Width, alignment, and fill”| Spec | Meaning |
|---|---|
:<10 | Left-align in width 10. |
:>10 | Right-align in width 10. |
:^10 | Center in width 10. |
:*^10 | Center, padding with *. |
:08 | Zero-pad to width 8. |
print(f"{'hi':<6}|") # hi |
print(f"{'hi':>6}|") # | hi -> right aligned
print(f"{'hi':^6}|") # | hi |
print(f"{42:08}") # 00000042
print(f"{'x':*^7}") # ***x***Thousands separators and percent
Section titled “Thousands separators and percent”print(f"{1000000:,}") # 1,000,000
print(f"{1234.5:,.2f}") # 1,234.50
print(f"{0.1234:.1%}") # 12.3% (percent with 1 decimal)
print(f"{255:#x}") # 0xff (hex with prefix)Number bases
Section titled “Number bases”| Type | Base |
|---|---|
:b | Binary |
:o | Octal |
:x / :X | Hex (lower/upper) |
:e | Scientific notation |
n = 255
print(f"{n:b}") # 11111111
print(f"{n:o}") # 377
print(f"{n:x}") # ff
print(f"{12345.678:.2e}") # 1.23e+04The = debug specifier (3.8+)
Section titled “The = debug specifier (3.8+)”Add = inside the braces to print both the expression and its value — perfect for quick debugging.
x = 10
y = 3
print(f"{x=}") # x=10
print(f"{x + y=}") # x + y=13
print(f"{x / y=:.2f}") # x / y=3.33 (combine with a format spec)Conversions: !r, !s, !a
Section titled “Conversions: !r, !s, !a”Apply repr(), str(), or ascii() before formatting with !r, !s, !a.
name = "Ada"
print(f"{name!r}") # 'Ada' (repr -> shows quotes)
print(f"{name!s}") # Ada (str)Nesting and dynamic specs
Section titled “Nesting and dynamic specs”Braces can contain expressions that themselves come from variables — even the format spec.
value = 3.14159
places = 3
print(f"{value:.{places}f}") # 3.142 (precision taken from a variable)
width = 10
print(f"{'hi':>{width}}") # right-align in a width from a variableMultiline f-strings and escaping braces
Section titled “Multiline f-strings and escaping braces”name, role = "Ada", "admin"
msg = (
f"User: {name}\n"
f"Role: {role}"
)
print(msg)
# To print literal braces, double them
print(f"{{not a placeholder}} but {name}") # {not a placeholder} but AdaCommon pitfalls
Section titled “Common pitfalls”- Forgetting the
f—"{x}"prints the braces literally;f"{x}"substitutes. - Literal braces need doubling —
{{and}}to print{and}. - Quote clashes — don’t reuse the outer quote inside (or use the other quote):
f"{d['key']}". - Heavy logic in braces hurts readability — compute first, then format.
Practice Exercises
Section titled “Practice Exercises”Exercise 1 – Two decimal places
Section titled “Exercise 1 – Two decimal places”Exercise 2 – Thousands separator
Section titled “Exercise 2 – Thousands separator”Exercise 3 – The debug specifier
Section titled “Exercise 3 – The debug specifier”Summary
Section titled “Summary”- f-strings embed any expression in
{}and are the fastest, clearest way to format strings. - The format spec (
:[fill][align][sign][width][,][.precision][type]) controls precision, padding, separators, and number bases. {expr=}prints the expression and its value — handy for debugging.- Use
!r/!s/!afor conversions, nest{...}for dynamic specs, and double{{ }}for literal braces.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading