How to use f-strings in Python

Python's f-strings transform string formatting into an elegant, readable solution. These formatted string literals let you embed expressions inside string constants using curly braces, making your code more concise and maintainable while improving performance.

This guide covers essential techniques, practical tips, and real-world applications for mastering f-strings. All code examples were created with Claude, an AI assistant built by Anthropic.

Basic f-string usage

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

The code demonstrates how f-strings embed variables directly into strings using curly braces. When Python encounters f"Hello, {name}!", it evaluates the expression inside the braces and converts it to a string—creating cleaner, more intuitive code compared to older formatting methods.

This approach offers several key advantages:

  • Improved readability by placing variables exactly where they appear in the output
  • Direct expression evaluation without separate formatting calls
  • Better performance than traditional string concatenation or .format() methods

Common f-string techniques

Building on these foundational advantages, f-strings offer powerful formatting capabilities through variable insertion, number formatting, and dynamic expression evaluation—three techniques that streamline string operations in Python.

Inserting variables with {}

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

The curly braces in f-strings act as placeholders that Python fills with variable values during string creation. When you write f"Welcome, {first_name} {last_name}!", Python replaces each {variable} with its corresponding value.

  • Variables inside curly braces can be any valid Python expression—not just variable names
  • The expression evaluation happens at runtime, making f-strings dynamic and flexible
  • Python automatically converts the evaluated expressions to strings, saving you from explicit type conversion

This direct variable insertion creates more maintainable code. You can easily spot where each value will appear in the final string, making your code's intent immediately clear to other developers.

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}")
Rounded to 2 decimal places: 12345.68
With commas: 12,345.68
Scientific notation: 1.23e+04

Precision specifiers in f-strings give you granular control over number formatting. The syntax follows a simple pattern: {value:format_spec}, where format_spec defines how the number should appear.

  • The .2f specification rounds decimals to 2 places, creating cleaner output for floating-point numbers
  • Adding a comma with ,.2f inserts thousand separators, making large numbers more readable
  • Scientific notation (.2e) converts numbers to exponential format—useful when working with very large or small values

These formatting options help you present numerical data precisely and professionally. You can adjust the number of decimal places by changing the digit after the dot, giving you full control over the output's appearance.

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}")
10 + 5 = 15
10 × 5 = 50
Is 10 greater than 5? True

F-strings evaluate Python expressions directly inside the curly braces, not just variables. This means you can perform calculations, comparisons, and other operations right within the string template.

  • Mathematical operations like {x + y} and {x * y} compute results immediately during string formatting
  • Comparison expressions such as {x > y} return boolean values that automatically convert to strings
  • You can include multiple expressions in a single f-string, making it perfect for creating readable mathematical or logical statements

The expressions can be as simple or complex as needed. Python evaluates them at runtime, converting the results to string format. This direct evaluation creates cleaner, more maintainable code compared to concatenating strings or using multiple print statements.

Advanced f-string features

Building on the expression evaluation capabilities, f-strings offer sophisticated features for aligning text, handling complex data structures, and streamlining debugging workflows.

Alignment and padding with format specifiers

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

Format specifiers in f-strings give you precise control over text alignment. The syntax :>10 right-aligns text in a 10-character space, while :<10 left-aligns it. For center alignment, use :^10.

  • The number after the alignment symbol (10) sets the total width of the space
  • Empty spaces automatically pad the text to maintain consistent width
  • The pipe symbol (|) in the example helps visualize the alignment boundaries

This formatting proves especially valuable when creating tables, columnar data, or any output that requires precise text positioning. The aligned output makes your data more readable and professionally formatted without complex string manipulation.

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}")
Name: Alice, Age: 30
Person: Bob

F-strings seamlessly integrate with Python's data structures, letting you access dictionary values and object attributes directly inside string templates. The curly braces evaluate expressions in real-time, making it simple to reference nested data.

  • Dictionary values appear using standard bracket notation: data['name'] pulls the value associated with that key
  • Object attributes work just like regular Python code—the expression Person('Bob').name creates an instance and accesses its name property
  • You can combine multiple lookups in a single f-string, creating clean and readable output without concatenation

This direct access to complex data structures makes f-strings particularly powerful for debugging, logging, and generating formatted reports. The syntax stays consistent whether you're working with simple variables or nested object properties.

Debugging with the = specifier

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

The = specifier in f-strings provides a powerful debugging shortcut by displaying both variable names and their values in a single line. When you add = after a variable name inside the curly braces, Python automatically shows the variable name followed by its value.

  • The expression {radius=} outputs radius=5 instead of just 5
  • You can combine the = specifier with other formatting options. For example, {area=:.2f} rounds the area to 2 decimal places while still showing the variable name
  • This feature eliminates the need to write repetitive debug print statements or remember variable names when inspecting values

This debugging enhancement particularly shines when tracking multiple variables or inspecting complex calculations. The output remains clean and readable while providing more context than traditional print statements.

Formatting log entries with timestamps

F-strings excel at creating standardized log entries by combining timestamps, user data, and event information into clear, consistent formats that help track application behavior over time.

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)

The code demonstrates how f-strings can format timestamps with precision. The datetime.now() function captures the current date and time. Inside the f-string, the timestamp formatting pattern %Y-%m-%d %H:%M:%S creates a standardized date-time string.

  • The %Y outputs a 4-digit year
  • The %m and %d show the month and day
  • The %H:%M:%S displays hours, minutes, and seconds in 24-hour format

The resulting output combines this formatted timestamp with user information in a structured format. This approach proves particularly useful when you need consistent, readable timestamps in your application's output.

Generating HTML content with f-strings

F-strings provide an elegant solution for dynamically generating HTML markup by seamlessly interpolating data from Python dictionaries and lists directly into HTML template strings.

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 demonstrates dynamic HTML table generation using Python data structures. The data list contains dictionaries representing people, with each person's name, age, and role stored as key-value pairs.

The script builds an HTML table string step by step. It starts with the table header row, then uses a for loop to create table rows (tr) and cells (td) for each person. The f-string inside the loop accesses dictionary values to populate each cell with the correct information.

  • The \n characters create line breaks for better HTML readability
  • The += operator appends new rows to the existing HTML string
  • Dictionary keys access each person's attributes: person['name'], person['age'], and person['role']

Common errors and challenges

Understanding common f-string pitfalls helps you write more reliable Python code while avoiding frustrating debugging sessions during string formatting operations.

Forgetting the f prefix when creating formatted strings

One of the most common mistakes when working with string formatting occurs when developers omit the f prefix before the quotation marks. Without this crucial prefix, Python treats curly braces as literal characters instead of placeholders for variable substitution.

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

The code outputs Hello, {name}! as plain text instead of inserting the variable's value. The curly braces remain unchanged because Python interprets them as literal characters. Let's examine the corrected version below.

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

Adding the f prefix transforms a regular string into an f-string, enabling Python to evaluate expressions inside curly braces. The corrected code properly interpolates the name variable into the greeting message, producing Hello, Python! as output.

  • Watch for missing f prefixes when strings don't format as expected
  • IDE syntax highlighting often helps catch this error by displaying curly brace content differently in f-strings
  • The error becomes more apparent during code review since the output contains literal {variable} text instead of values

Escaping curly braces in f-strings

When you need to include literal curly braces in an f-string, Python's default behavior interprets them as variable placeholders. This creates errors when the interpreter attempts to substitute nonexistent variables. The code below demonstrates this common challenge.

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

The code fails because Python can't find a variable named brackets to substitute. The interpreter expects every set of curly braces in an f-string to contain a valid expression. Here's the correct approach to escape braces:

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

Double curly braces in f-strings tell Python to treat them as literal characters instead of variable placeholders. When you write {{brackets}}, Python outputs a single set of braces in the final string. This technique proves essential when formatting strings that need to include curly braces for syntax or styling purposes.

  • Watch for this issue when working with JSON templates, CSS styles, or other formats that use curly braces
  • Remember that single braces in f-strings always trigger variable substitution
  • The rule is simple: use double braces to display one brace in the output

Type errors when formatting numeric values in f-strings

Type errors commonly occur when applying numeric format specifiers to string values in f-strings. The :.2f format specifier expects a floating-point number but raises a TypeError when encountering string data. This mismatch between data types and format specifications creates runtime errors.

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

The :.2f format specifier attempts to format a string value as a floating-point number. Since Python can't directly apply decimal formatting to strings, it raises a TypeError. The solution appears in the code below.

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

Converting string values to numbers before applying numeric format specifiers prevents type errors in f-strings. The float() function transforms the string "123.456" into a floating-point number that works with the :.2f format specifier.

  • Watch for numeric strings from user input, file reading, or API responses
  • Always validate and convert data types before formatting
  • Consider using exception handling with float() conversion to gracefully handle invalid inputs

This pattern becomes especially important when processing financial data or scientific calculations where precise decimal formatting matters. The solution ensures your code handles various data sources reliably while maintaining accurate numeric representations.

FAQs

What is the basic syntax for creating an f-string in Python?

F-strings in Python start with the letter f or F before the opening quotation mark. Place expressions inside curly braces {} within the string to evaluate them at runtime. For example, f"Total: {price}" will insert the value of the price variable.

This syntax offers a more readable and maintainable way to format strings compared to older methods. Python evaluates the expressions inside the braces and converts the results to strings automatically—making your code cleaner and more intuitive.

How do you include variables inside f-string expressions?

F-strings let you embed Python expressions inside string literals by prefixing the string with f and wrapping variables in curly braces {}. The Python interpreter evaluates these expressions at runtime, converting results to strings.

Inside the curly braces, you can include:

  • Simple variables like f"Hello {name}"
  • Method calls such as f"Title: {title.upper()}"
  • Calculations like f"Total: {price * quantity}"

This approach offers cleaner syntax and better performance than older string formatting methods. The expressions get evaluated in the current scope, making f-strings both powerful and intuitive to use.

Can you perform calculations directly within f-string curly braces?

Yes, you can perform calculations inside f-string curly braces in Python. When you write expressions like f"{2 * 3}", Python evaluates the mathematical operation before converting the result to a string. This feature supports arithmetic operations, function calls, and even conditional expressions.

The f-string parser processes everything between the curly braces as a complete Python expression. This means you can write complex calculations like f"{(x + y) * z:.2f}" to format the result with specific precision. The evaluation happens at runtime, making f-strings both powerful and flexible for string formatting needs.

What happens if you need to include actual curly braces in your f-string output?

To include literal curly braces in f-strings, you'll need to double them up. When you write {{ or }} in an f-string, Python interprets them as a single brace in the output. This works because Python's f-string parser treats doubled braces as an escape sequence.

For example, writing f"Value: {{variable}}" will output the literal text "Value: {variable}" instead of attempting string interpolation. This approach maintains readability while clearly distinguishing between literal braces and interpolation markers.

Are f-strings available in all versions of Python?

F-strings (f"...") first appeared in Python 3.6. Before this version, developers used older string formatting methods like .format() or % operator. Python introduced f-strings to make string interpolation more readable and intuitive.

The feature combines the clarity of template literals with Python's existing string formatting capabilities. F-strings also execute expressions in real-time, making them more efficient than alternative methods. If you're working with Python 3.5 or earlier, you'll need to use the traditional formatting approaches.

🏠