How to use f-strings in Python

Learn how to use Python f-strings with examples, tips, and real-world applications. We also cover common errors and how to debug them.

How to use f-strings in Python
Published on: 
Fri
Feb 13, 2026
Updated on: 
Mon
Apr 13, 2026
The Replit Team

Python's f-string provides a concise and readable way to format strings. This feature simplifies how you embed expressions inside string literals for dynamic output.

You'll learn key techniques, tips, and real-world applications. You will also find debugging advice to master f-string formatting for cleaner, more efficient Python code.

Basic f-string usage

name = "Python"
message = f"Hello, {name}!"
print(message)--OUTPUT--Hello, Python!

The key is the f prefix before the string literal, which tells Python to evaluate expressions inside the string. This is why the code works. The interpreter finds the expression wrapped in curly braces, {name}, and replaces it with the variable's value at runtime.

This method directly embeds the logic within the string itself. You're not managing separate arguments or placeholders, which makes the connection between your data and the output much more intuitive, readable, and memory-efficient.

Common f-string techniques

While the basic syntax is straightforward, you can unlock more control over your strings by using expressions and format specifiers within the {}.

Inserting variables with {}

first_name = "Ada"
last_name = "Lovelace"
greeting = f"Welcome, {first_name} {last_name}!"
print(greeting)--OUTPUT--Welcome, Ada Lovelace!

This technique isn't limited to a single variable. You can embed multiple expressions within one f-string, as shown by combining first_name and last_name. Python seamlessly evaluates each placeholder and inserts its value into the final string.

  • You can include any number of {} placeholders.
  • The expressions are replaced with their values in the order they appear.
  • This approach is often cleaner and more intuitive than joining strings with the + operator.

Formatting numbers with precision specifiers

value = 12345.6789
print(f"Rounded to 2 decimal places: {value:.2f}")
print(f"With commas: {value:,.2f}")
print(f"Scientific notation: {value:.2e}")--OUTPUT--Rounded to 2 decimal places: 12345.68
With commas: 12,345.68
Scientific notation: 1.23e+04

Format specifiers give you fine-grained control over your output. By adding a colon : after your expression, you can tell Python exactly how to format the value. This is especially useful for formatting numbers in Python.

In the example:

  • :.2f rounds the value to two decimal places using fixed-point notation.
  • The comma in :,.2f adds thousands separators.
  • :.2e switches the output to scientific notation.

Using expressions inside {}

x = 10
y = 5
print(f"{x} + {y} = {x + y}")
print(f"{x} × {y} = {x * y}")
print(f"Is {x} greater than {y}? {x > y}")--OUTPUT--10 + 5 = 15
10 × 5 = 50
Is 10 greater than 5? True

The curly braces in an f-string aren't limited to just variables; you can embed any valid Python expression. Python evaluates the expression when the string is created and inserts the resulting value.

  • You can perform arithmetic operations like x + y directly inside the string.
  • It also works for comparisons, such as x > y, which will evaluate to True or False.
  • The result of any expression is automatically converted into its string representation for you.

Advanced f-string features

Building on the fundamentals, f-strings also offer more sophisticated tools for controlling alignment, working with complex data, and even debugging with the = specifier.

Alignment and padding with format specifiers

names = ["Alice", "Bob", "Charlie"]
for name in names:
print(f"{name:>10} | {name:<10} | {name:^10}")--OUTPUT--Alice | Alice | Alice
Bob | Bob | Bob
Charlie | Charlie | Charlie

F-strings let you align text within a fixed-width space, which is perfect for formatting columns or reports. You achieve this by adding an alignment specifier after the colon in your placeholder. The number that follows sets the total width of the field.

  • Use < for left alignment.
  • Use > for right alignment.
  • Use ^ for center alignment.

In the example, expressions like {name:>10} push the text to the right within a 10-character space, making your console output much easier to read.

Working with dictionaries and objects

data = {"name": "Alice", "age": 30}
print(f"Name: {data['name']}, Age: {data['age']}")

class Person:
def __init__(self, name):
self.name = name

print(f"Person: {Person('Bob').name}")--OUTPUT--Name: Alice, Age: 30
Person: Bob

F-strings aren't limited to simple variables; they also handle complex data structures like dictionaries and objects. You can directly embed expressions for accessing dictionary values by key, such as data['name'], or access object attributes using dot notation, like Person('Bob').name.

  • Pay attention to your quotes. When an f-string uses double quotes, you must use single quotes for dictionary keys inside the braces to avoid syntax errors.
  • This flexibility lets you build descriptive strings from your data structures in a clean, readable way.

Debugging with the = specifier

radius = 5
area = 3.14159 * radius**2
print(f"{radius=}, {area=:.2f}")--OUTPUT--radius=5, area=78.54

The = specifier is a handy debugging shortcut. It automatically prints the expression text, an equals sign, and its evaluated value. This lets you quickly inspect variables without manually typing their names twice, like in f"radius = {radius}". This debugging approach aligns well with vibe coding, where you iterate quickly and need immediate feedback on your code's behavior.

  • It’s a clean way to see what’s happening inside your code at a glance.
  • You can also combine it with other format specifiers. For example, {area=:.2f} applies rounding after showing the variable's name and value.

Move faster with Replit

Replit is an AI-powered development platform where all Python dependencies come pre-installed, so you can skip setup and start coding instantly. While mastering f-strings is a great step, you can build even faster with Agent 4, which helps you move from piecing together techniques to building complete applications.

Instead of just formatting strings, you can build tools that use that skill:

  • A currency converter that displays results formatted with specific decimal precision and thousands separators.
  • A command-line tool that generates reports by aligning text into perfectly formatted columns.
  • A debugging utility that pulls data from objects and displays it clearly, similar to using the = specifier but for a full report.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Even with their simplicity, f-strings have a few common pitfalls that can trip you up if you're not careful.

  • Forgetting the f prefix: It’s a simple but common mistake. If you leave out the f, Python won't evaluate the expressions in your curly braces. Instead of seeing the variable's value, your string will literally contain the placeholder text, like {name}.
  • Escaping curly braces: Sometimes you need to include actual curly braces in your final string. Since f-strings use {} for expressions, you have to tell Python you want the literal characters. You can do this by doubling them up: use {{ to get a single { and }} for a single }.
  • Type errors when formatting: Format specifiers are type-sensitive. Applying a numeric format, such as :.2f for rounding, to a non-numeric value will cause a TypeError. Always make sure your variable's data type matches the format you're trying to apply.

Forgetting the f prefix when creating formatted strings

This is a simple but very common mistake. If you forget the f prefix, Python won't evaluate the expressions in your curly braces. Instead, your string will literally contain the placeholder text, like {name}. The following code demonstrates this common pitfall.

name = "Python"
message = "Hello, {name}!" # Missing f prefix
print(message)

The output is Hello, {name}! because Python treats it as a standard string, not an f-string. The {name} placeholder is never evaluated. See how a small change in the code below corrects this.

name = "Python"
message = f"Hello, {name}!" # Added f prefix
print(message)

With the f prefix added, Python correctly evaluates the expression inside the curly braces, producing the intended Hello, Python! output. This simple mistake is easy to make, especially when refactoring existing code or copying snippets. Always double-check that your formatted strings start with an f to ensure Python interprets them correctly. Without it, a placeholder like {name} is treated as plain text.

Escaping curly braces in f-strings

What if you need to print literal curly braces within your string? You can't just type them directly, because f-strings use the {} characters to evaluate expressions. This creates a conflict, as the following code demonstrates when it fails.

value = 42
template = f"The value is {value} in {brackets}" # Will try to substitute {brackets}
print(template)

This code triggers a NameError because Python searches for a variable named brackets that doesn't exist. The example below demonstrates the correct syntax for including literal braces in your output without causing an error.

value = 42
template = f"The value is {value} in {{brackets}}" # Double braces to escape them
print(template)

The solution is to double the curly braces. By writing {{ and }}, you're telling Python to print literal braces instead of looking for a variable to substitute. This avoids a NameError when the content inside the braces isn't a valid expression. You'll need this technique anytime you're formatting strings that must contain examples of code, placeholders, or any text that naturally uses curly braces.

Type errors when formatting numeric values in f-strings

Format specifiers are powerful, but they’re also type-sensitive. Applying a numeric format like :.2f to a non-numeric value will raise a TypeError, even if the string contains what looks like a number. The following code demonstrates this common pitfall.

value = "123.456" # String value
formatted = f"Amount: ${value:.2f}" # Will raise TypeError
print(formatted)

The :.2f format specifier is strictly for numbers, but the value variable holds a string. Python won't automatically convert it, which causes the error. The corrected code below shows how to handle this properly.

value = "123.456" # String value
formatted = f"Amount: ${float(value):.2f}" # Convert to float first
print(formatted)

The fix is to explicitly convert the string to a number before formatting. By wrapping value in float(), you change its type from a string to a float. Now, the :.2f specifier works because it's operating on a number. This error often appears when you're working with data from files or user input, which is usually read as text, so it's important to ensure your data type matches the format specifier. For more complex debugging scenarios, Replit's code repair feature can help identify and fix these type mismatches automatically.

Real-world applications

Now that you've navigated the common pitfalls, you can apply f-strings to practical tasks like formatting log entries and generating dynamic HTML.

Formatting log entries with timestamps

You can create clear and structured log entries by using f-strings to embed dynamic data and apply custom formatting directly to timestamps.

from datetime import datetime

timestamp = datetime.now()
user_id = 12345
action = "login"
log_entry = f"[{timestamp:%Y-%m-%d %H:%M:%S}] User {user_id} performed {action}"
print(log_entry)

This example showcases how f-strings handle complex objects, not just simple variables. The key is the format specifier applied directly to the timestamp object.

  • The code :%Y-%m-%d %H:%M:%S instructs Python to format the datetime object into a standard year-month-day and hour-minute-second format.
  • This is done inside the f-string, so you don't need a separate step like calling the strftime() method.

The result is a clean, readable log entry assembled from different data types in one line. For complete logging solutions, learn about creating log files in Python.

Generating HTML content with f-strings

You can also use f-strings to dynamically generate HTML, which is especially useful for building tables or lists from your data.

data = [
{"name": "Alice", "age": 28, "role": "Developer"},
{"name": "Bob", "age": 35, "role": "Manager"},
{"name": "Charlie", "age": 24, "role": "Designer"}
]

html = "<table>\n <tr><th>Name</th><th>Age</th><th>Role</th></tr>"
for person in data:
html += f"\n <tr><td>{person['name']}</td><td>{person['age']}</td><td>{person['role']}</td></tr>"
html += "\n</table>"

print(html)

This code builds an HTML table by repeatedly adding to a string inside a loop. An f-string generates each table row by pulling values from a dictionary, like person['name'], and embedding them directly into the HTML structure.

  • The += operator is key here; it appends each newly formatted row to the main html string.
  • This approach is great for simple dynamic content generation, turning Python data structures into formatted text for reports or web pages without extra libraries. For more complex web applications, AI coding with Python can help you build complete systems that leverage these string formatting techniques.

Get started with Replit

Put your knowledge into practice and build a real tool. Describe what you want to Replit Agent, like "build a tip calculator that formats currency" or "generate a status report with aligned text columns."

Replit Agent writes the code, tests for errors, and deploys the app for you. Turn your concept into a finished product. Start building with Replit.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.