Understanding Python String Formatting (f-strings)
SkillVeris Team
Engineering Team

An f-string is a string prefixed with f that lets you embed Python expressions directly inside curly braces, evaluated at runtime.
In this guide, you'll learn:
- F-strings are more readable and generally faster than older % formatting and str.format() approaches.
- Format specifiers after a colon control decimals, padding, alignment, thousands separators, and number bases.
- The = sign inside braces prints both the expression and its value, making f-strings a quick debugging tool (Python 3.8+).
- You can call functions, do arithmetic, and access attributes inside the braces of an f-string.
1What Are F-strings?
An f-string, short for formatted string literal, is a string prefixed with the letter f that lets you embed Python expressions inside curly braces. When the program runs, Python evaluates each expression and inserts its value into the string. Introduced in Python 3.6, f-strings are now the preferred way to build strings.
They replace older, clunkier methods. Instead of concatenating with + or juggling placeholders, you write the variable right where it belongs, which keeps the output template and its values side by side and easy to read.
- name = 'Ava'; age = 29
- print(f'{name} is {age} years old') # Ava is 29 years old
- total = f'{2 + 3} items' # 5 items — expressions work too
2Why F-strings Beat the Alternatives
Python has three formatting styles: old % formatting, str.format(), and f-strings. F-strings win on readability because the values appear inline instead of in a separate argument list, and they are generally the fastest of the three at runtime.
- old = 'Hello %s, you are %d' % (name, age) # % style
- mid = 'Hello {}, you are {}'.format(name, age) # .format style
- new = f'Hello {name}, you are {age}' # f-string — clearest
🔑Key Idea
Reach for f-strings by default. Keep str.format() only when you need a reusable template string defined separately from its values.
3Formatting Numbers
A colon inside the braces introduces a format specifier that controls how a value is displayed. This is where f-strings become powerful: rounding decimals, adding thousands separators, and showing percentages all take a short code after the colon.
- pi = 3.14159
- f'{pi:.2f}' # '3.14' — two decimal places
- f'{1234567:,}' # '1,234,567' — thousands separator
- f'{0.256:.1%}' # '25.6%' — percentage
- f'{255:x}' # 'ff' — hexadecimal
- f'{42:08.2f}' # '00042.00' — zero-padded width 8
4Aligning and Padding Text
Format specifiers also control alignment and width, which is invaluable for printing tidy tables in the terminal. Use < for left, > for right, and ^ for center alignment, optionally with a fill character.
- f'{"left":<10}|' # 'left |'
- f'{"right":>10}|' # ' right|'
- f'{"mid":^10}|' # ' mid |'
- f'{"pad":*^10}|' # '***pad****|' — custom fill
Building a Simple Table
Combining alignment specifiers lets you line up columns without external libraries. Each cell gets a fixed width so the columns stay straight.
for item, price in [('Coffee', 3.5), ('Tea', 2.0)]:
print(f'{item:<10}{price:>6.2f}')5Expressions and the Debug Equals Sign
Anything that produces a value can go inside the braces: arithmetic, function calls, method calls, and attribute access. Python 3.8 added a debugging shortcut — putting = after the expression prints both the code and its result.
- items = [1, 2, 3]
- f'Count: {len(items)}' # 'Count: 3'
- f'Upper: {name.upper()}' # 'Upper: AVA'
- f'{age=}' # 'age=29' — great for quick debugging
💡Pro Tip
The f'{value=}' syntax is a fast debugging trick: it prints the variable name and its value together, saving you from typing them twice in print calls.
6Escaping Braces and Multi-line Strings
To include a literal curly brace in the output, double it. F-strings also work with triple quotes for multi-line templates, which is handy for generating blocks of text or simple reports.
- f'{{literal braces}}' # '{literal braces}'
- f'''\nName: {name}\nAge: {age}\n''' # multi-line output
- f'{price:.2f}% growth'.replace('%', ' percent') # combine freely
7Common Mistakes to Avoid
F-strings are forgiving, but a few errors show up repeatedly.
- Forgetting the f prefix — 'Hello {name}' prints the braces literally with no substitution.
- Using the same quote character inside and outside — in older Python, f'{d['key']}' clashes; use different quotes or a variable.
- Putting a backslash directly inside the braces in versions before 3.12 — assign it to a variable first.
- Confusing single braces with literal ones — double them when you want an actual brace in the output.
- Overloading one f-string with heavy logic — extract complex expressions into variables for readability.
⚠️Watch Out
Without the leading f, the string is a plain literal and the braces are printed as-is. If your variables are not being substituted, the missing f prefix is the first thing to check.
8Key Takeaways
F-strings are the modern default for building strings in Python.
- Prefix a string with f and embed expressions in curly braces.
- A colon introduces format specifiers for decimals, padding, and alignment.
- Use :,.2f for money-style numbers and :.1% for percentages.
- The {expr=} form prints both the expression and its value for debugging.
- Double a brace to print a literal one, and never forget the f prefix.
9Frequently Asked Questions
Q: What Python version added f-strings? A: F-strings arrived in Python 3.6. The debug syntax with a trailing equals sign, like f'{x=}', was added in Python 3.8. If you are on any modern Python, f-strings are available.
Q: How do I round a number in an f-string? A: Use a format specifier after a colon: f'{value:.2f}' rounds to two decimal places. You can change the digit to control precision, for example :.0f for a whole number or :.4f for four decimals.
Q: How do I print a literal curly brace in an f-string? A: Double it. Writing f'{{}}' outputs a single pair of braces, {}. A single brace is interpreted as the start of an expression, so doubling escapes it.
Q: Are f-strings faster than .format()? A: Generally yes. Because the expressions are parsed at compile time, f-strings usually run faster than str.format() and % formatting, in addition to being more readable. They are the recommended choice for most code.
Related Reading
Get The Print Version
Download a PDF of this article for offline reading.
About the Publisher
SkillVeris Team
Engineering Team
Our engineering writers turn abstract code concepts into hands-on, project-driven learning experiences.
View all postsRelated Posts
Never miss an update
Get the latest tutorials and guides delivered to your inbox.
No spam. Unsubscribe anytime.