track
Python String Interpolation: A Beginner's Guide
Suppose you want to output a person's name and profession. You could write a simple program as follows.
# Define variables
name = 'Mark'
profession = 'Astronaut'
age = 7
# Output info
output_string = ('My name is ' + name +
', I am ' + str(age) + ' years old ' +
'and my profession is ' + profession + '.')
print(output_string)
My name is Mark, I am 7 years old and my profession is Astronaut.
That approach lacks conciseness and readability. Fortunately, string interpolation offers a better solution. It allows variables, expressions, or function outputs to be inserted directly into a string, making string manipulation dynamic and eliminating the need for manual concatenation.
Using a string interpolation approach, we could rewrite the code as follows.
# Define variables
name = 'Mark'
profession = 'Astronaut'
age = 7
# Output info
output_string = f'My name is {name}, I am {age} years old and my profession is {profession}.'
print(output_string)
My name is Mark, I am 7 years old and my profession is Astronaut.
The version with string interpolation allows for embedding expressions directly inside of the string without the use of messy concatenations. As you can see, it is a much cleaner approach.
Basic String Interpolation in Python
There are several different string interpolation techniques available in Python. The most commonly recommended method is formatted string literals, also known as f-strings, which have been available since Python 3.6.
Another method, commonly seen in code older than Python 3.6, is the .format()
method. Although this method is more verbose than f-strings, it occasionally has advantages (details below).
Finally, you may encounter %
-style formatting in legacy code.
Using f-strings (Python 3.6+)
f-strings (formatted string literals) are a powerful and concise way to format strings in Python. They were introduced in Python 3.6 and provide a readable and efficient way to insert variables, expressions, and function calls directly into strings.
A simple example of the basic syntax of an f-string is as follows.
name = 'Mark'
output_string = f'My name is {name}.'
print(output_string)
My name is Mark.
In this code, the output_string
variable is assigned an f-string. The f
prefix before the opening quote indicates that the string supports embedded expressions. The variable name
is evaluated and its value is inserted into the string, resulting in the output: "My name is Mark."
Not only variable values, but also calculations or expressions may be inserted into f-strings. Consider this example.
import math
a = 3.0
b = 4.0
# Use string interpolation for the formula
print(f'The hypotenuse of a triangle with base {a} and side {b} is {math.sqrt(a ** 2 + b ** 2)}.')
The hypotenuse of a triangle with base 3.0 and side 4.0 is 5.0.
The expression math.sqrt(a ** 2 + b ** 2)
is evaluated directly within the string, eliminating the need to compute the value separately before inserting it into the string.
Using the .format() method
Like f-strings, the .format()
method allows inserting variables and expressions into a string. The basic syntax of the .format()
method is as follows.
name = 'Mark'
output_string = 'My name is {}.'.format(name)
print(output_string)
My name is Mark.
The curly brackets {}
serve as a placeholder, signaling that a variable's value will be inserted into the string at that position. The specific variable's value inserted into the placeholder is determined by the argument provided to the .format()
method.
Positional arguments
What happens if you need multiple placeholders for multiple variables? Consider the following code.
name = 'Mark'
age = 7
# The placeholders are filled in order of the arguments
output_string = 'My name is {} and I am {} years old.'.format(name, age)
print(output_string)
My name is Mark and I am 7 years old.
In this example, two variables, name
and age
, are needed. Consequently, the string includes two placeholders, and the variables are inserted in the same order they appear in the .format()
method. These arguments are known as *positional* arguments because their placement in the string is determined by their position in the method’s argument list.
Indexed and named placeholders
As a variation of the placeholder idea, consider this example.
name = 'Mark'
age = 7
# Print age twice
output_string = 'My name is {} and I am {} years old. My twin brother is also {} years old.'.format(name, age, age)
print(output_string)
My name is Mark and I am 7 years old. My twin brother is also 7 years old.
Here, we reused the value of the variable age
twice. Including the same variable multiple times like this is clunky and detracts from readability. Is there a way to reuse a variable in string formatted with the .format()
method without repeating it? Yes, there is, using so-called *indexed placeholders*.
name = 'Mark'
age = 7
# Use indexed placeholders
output_string = 'My name is {0} and I am {1} years old. My twin brother is also {1} years old.'.format(name, age)
print(output_string)
My name is Mark and I am 7 years old. My twin brother is also 7 years old.
In this example, we explicitly defined the order of variables within the curly brackets, following Python’s zero-based indexing. Additionally, we reused the variable at index 1 instead of repeating it.
As an alternative to positional indexing, you can also use named arguments, where each argument is given a name.
print('My name is {name} and I am {age} years old.'.format(name='Mark', age=7))
My name is Mark and I am 7 years old.
The named argument is evaluated within the curly brackets that specify its name. As a result, the {name}
placeholder is replaced with the value "Mark"
, and the {age}
placeholder is replaced with 30
.
Using the % operator
The final method for string interpolation is the %
operator. It functions similarly to the printf()
command in C. Its use is deprecated and strongly discouraged in favor of f-strings or the .format()
method. It is mentioned here because you may encounter it in legacy codebases.
The basic format for the %
operator is: "format string" % values
. The format string contains placeholders, such as %s
for strings, that get replaced by values. For example, the following example prints "Hello, Mark."
'Hello %s' % 'Mark'
'Hello Mark'
Other common format specifiers are shown in the following table.
Specifier |
Meaning |
Example |
---|---|---|
%s |
String |
"Hello %s" % "Alice" → "Hello Alice" |
%d |
Integer (Decimal) |
"Age: %d" % 25 → "Age: 25" |
%f |
Float (Default 6 decimals) |
"Pi: %f" % 3.14159 → "Pi: 3.141590" |
%.nf |
Float (n decimal places) |
"%.2f" % 3.14159 → "3.14" |
%x |
Hexadecimal (lowercase) |
"%x" % 255 → "ff" |
%X |
Hexadecimal (uppercase) |
"%X" % 255 → "FF" |
%o |
Octal |
"%o" % 255 → "377" |
The % operator has many limitations. For one thing, it is less readable than f-strings. Consider the following code.
name = "Alice"
age = 30
height = 5.6
# The % operator is hard to scan
message = "My name is %s, I am %d years old, and my height is %.1f feet." % (name, age, height)
print(message)
My name is Alice, I am 30 years old, and my height is 5.6 feet.
Is this code clear at a glance? Probably not. There is a lot of visual parsing back and forth from the placeholder and the variables that fill in the blanks. It's easy to get confused (or dizzy) with all that scanning back and forth.
Now, consider equivalent code using f-strings.
# This is much cleaner
message = f"My name is {name}, I am {age} years old, and my height is {height:.1f} feet."
print(message)
My name is Alice, I am 30 years old, and my height is 5.6 feet.
No scanning and no obscure formatting strings are required. The code is clean, easy to understand, and easy to write. You can learn other tips to write clear, optimized code with DataCamp’s Python Programming skill track.
Advanced Python String Interpolation Techniques
Now that we’ve understood the basics of Python string interpolation, let’s look at some more advanced uses.
Python multiline string interpolation
f-strings can also be used for multiline content by using the f signifier with triple quotes (either single or double). The text can be written across multiple lines, and it will appear in the output exactly as formatted.
name = 'Mark'
profession = 'Astronaut'
age = 7
# This is an example of a multiline string
bio = f"""
Name: {name}
Profession: {profession}
Age: {age}
"""
print(bio)
Name: Mark
Profession: Astronaut
Age: 7
Multiline strings can also be created using the .format()
method.
name = 'Mark'
profession = 'Astronaut'
age = 7
# This is a multiline string with .format()
bio = """
Name: {}
Profession: {}
Age: {}
""".format(name, profession, age)
print(bio)
Name: Mark
Profession: Astronaut
Age: 7
Use cases for multiline string interpolation
Why would you want to use multiline string interpolation? There are many uses for multiline string interpolation. Here are a few use cases:
- Generating multiline emails or messages
- Logging and debugging
- Generating SQL queries dynamically
Generating multiline emails or messages
Suppose you are sending out a form letter to many invitees to a tech conference.
name = "Alice"
event = "Annual Tech Conference"
date = "March 15, 2025"
email = """Dear {name},
We are pleased to invite you to the {event} taking place on {date}.
We hope you can join us for an exciting experience.
Best regards,
The Event Team""".format(name=name, event=event, date=date)
print(email)
Dear Alice,
We are pleased to invite you to the Annual Tech Conference taking place on March 15, 2025.
We hope you can join us for an exciting experience.
Best regards,
The Event Team
With f-strings, creating a form letter is simple and efficient. To change the name, event, or date, simply change them in the variables and the string changes automagically.
Logging and debugging
Multiline strings are useful for printing out error messages for logs.
error_code = 404
url = '/missing-page'
timestamp = '2025-02-05 12:30:00'
error_message = 'The requested page could not be found.'
log_message = f"""[ERROR {error_code}]
Time: {timestamp}
URL: {url}
{error_message}"""
print(log_message)
[ERROR 404]
Time: 2025-02-05 12:30:00
URL: /missing-page
The requested page could not be found.
This method keeps log messages structured and makes debugging easier with properly formatted logs.
Generating SQL queries dynamically
SQL queries can be built dynamically using multiline strings.
table = 'users'
column = 'email'
value = 'alice@example.com'
query = f"""SELECT *
FROM {table}
WHERE {column} = '{value}';"""
print(query)
SELECT *
FROM users
WHERE email = 'alice@example.com';
This method makes SQL queries readable and maintains indentation. Furthermore, it eliminates the need to use +
for string concatenation.
Other use cases include:
- Writing formatted contracts
- Creating Markdown or $\LaTeX$ documents
- Multiline HTML/XML templates
- Generating API responses or JSON-like text
Advantages of multiline string interpolation
As we can see, there are several advantages of multiline string interpolation.
- String interpolation preserves formatting without needing the escape character
\n
. - String interpolation improves readability compared to single-line formatting.
- String interpolation reduces clutter when working with structured text (e.g., logs, queries, reports).
- String interpolation allows dynamic text generation without breaking indentation.
Formatting numbers and special values
To control the number of decimal places displayed using an f-string, use the syntax: f'{value:.nf}'
, where value
is the floating-point number, n
is the number of decimal places, and f
(the one after the .
) stands for float formatting.
To illustrate, the following code outputs $\pi$ to different decimal places.
pi = 3.1415926535
print(f'Pi rounded to 2 decimal places: {pi:.2f}')
print(f'Pi rounded to 4 decimal places: {pi:.4f}')
print(f'Pi rounded to 0 decimal places: {pi:.0f}')
Pi rounded to 2 decimal places: 3.14
Pi rounded to 4 decimal places: 3.1416
Pi rounded to 0 decimal places: 3
Formatting with the .format()
method is similar.
print('Pi rounded to 2 decimal places: {:.2f}'.format(pi))
print('Pi rounded to 4 decimal places: {:.4f}'.format(pi))
print('Pi rounded to 0 decimal places: {:.0f}'.format(pi))
Pi rounded to 2 decimal places: 3.14
Pi rounded to 4 decimal places: 3.1416
Pi rounded to 0 decimal places: 3
You can use an f-string to format percentages by using the :.nf
syntax combined with %
, where n
is the number of decimal places.
score = 0.875
print(f"Success rate: {score:.2%}")
Success rate: 87.50%
You can use an f-string to format currency by using the :,
for thousands separators and .nf
to control decimal places. You can also include a currency symbol like $, €, or £ directly in the string.
amount = 98765.4321
print(f"USD: ${amount:,.2f}")
print(f"EUR: €{amount:,.2f}")
print(f"GBP: £{amount:,.2f}")
USD: $98,765.43
EUR: €98,765.43
GBP: £98,765.43
Using f-strings with dictionaries and lists
To use f-strings with a dictionary in Python, accessing dictionary values inside the curly brackets using square bracket notation (dict['key']) or by unpacking the dictionary with **.
person = {
'name': 'Alice',
'age': 30,
'city': 'New York'
}
print(f"My name is {person['name']}, I am {person['age']} years old, and I live in {person['city']}.")
My name is Alice, I am 30 years old, and I live in New York.
Instead of accessing each key manually, you can unpack the dictionary into an f-string as follows.
person = {
'name': 'Alice',
'age': 30,
}
print(f'My name is {name} and I am {age} years old.'.format(**person))
My name is Alice and I am 7 years old.
To avoid an error for missing keys, use get()
for dictionary access.
person = {"name": "Alice"}
# Error: key 'city' is missing
print(f"City: {person['city']}")
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[87], line 4
1 person = {"name": "Alice"}
3 # Error: key 'city' is missing
----> 4 print(f"City: {person['city']}")
KeyError: 'city'
print(f"City: {person.get('city', 'Not specified')}")
City: Not specified
Pros and Cons of String Interpolation Methods
As we have seen, f-strings and the .format()
method are both useful methods for string interpolation. Let's look at a comparison of the pros and cons of each method.
Feature |
f-strings |
.format() |
% formatting |
---|---|---|---|
Readability |
🟢 Best |
🟡 OK |
🔴 Harder |
Performance |
🟢 Fastest |
🟡 Slower |
🔴 Slowest |
Supports Expressions |
🟢 Yes |
🟡 Indirect |
🔴 No |
multiline Support |
🟢 Yes |
🟢 Yes |
🔴 No |
Ease of Use |
🟢 Easiest |
🟡 Medium |
🔴 Hard |
Debugging (= Operator) |
🟢 Yes (Python 3.8+) |
🔴 No |
🔴 No |
When should you use .format()
over f-strings?
Advantage |
Why use .format() |
---|---|
Legacy Python Support |
Works in Python 2.7+ |
Flexible Ordering |
Allows easy reorder of placeholders |
Dynamic Formatting |
Works when the format specifier is dynamic |
Handles {} Braces Better |
Avoids extra manual escaping |
Works Well with Dictionaries |
Easier to use dict keys |
Common Pitfalls and Best Practices
Below, you can find some troubleshooting methods and top tips for using Python string interpolation.
Avoiding syntax errors with curly braces
There are many syntax errors one can make when using string interpolation involving curly braces.
- Ensure every { has a matching }
print('Hello, my name is {name!'}
Cell In[96], line 1
print('Hello, my name is {name!'}
^
SyntaxError: closing parenthesis '}' does not match opening parenthesis '('
Fortunately, the error is straightforward, and the fix is easy.
- Use {{ and }} for displaying literal {}
What happens if you want to print curly braces within an interpolated string? Anything inside of curly brackets will (attempt to) be evaluated.
print(f'Set notation: {a, b, c}')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[101], line 1
----> 1 print(f'Set notation: {a, b, c}')
NameError: name 'c' is not defined
Python interprets a, b, c inside the curly brackets as a tuple, attempting to find a value associated with a. Since no such variable exists, it raises a KeyError. The fix is to use double curly brackets {{}}
.
print("Set notation: {{a, b, c}}")
Set notation: {{a, b, c}}
Performance comparison: f-strings vs .format()
Let's compare the performance of f-strings and .format()
.
import timeit
name = "Alice"
age = 30
pi = 3.1415926535
# Measure f-string performance
f_string_time = timeit.timeit('f"My name is {name} and I am {age} years old."', globals=globals(), number=1000000)
# Measure .format() performance
format_time = timeit.timeit('"My name is {} and I am {} years old.".format(name, age)', globals=globals(), number=1000000)
# Measure f-string performance with expressions
f_string_expr_time = timeit.timeit('f"Pi rounded to 2 decimal places: {pi:.2f}"', globals=globals(), number=1000000)
# Measure .format() performance with expressions
format_expr_time = timeit.timeit('"Pi rounded to 2 decimal places: {:.2f}".format(pi)', globals=globals(), number=1000000)
# Print results
print(f"f-string (simple): {f_string_time:.6f} seconds")
print(f".format() (simple): {format_time:.6f} seconds")
print(f"f-string (with expression): {f_string_expr_time:.6f} seconds")
print(f".format() (with expression): {format_expr_time:.6f} seconds")
f-string (simple): 0.080447 seconds
.format() (simple): 0.129860 seconds
f-string (with expression): 0.123171 seconds
.format() (with expression): 0.146242 seconds
As you can see, from an efficiency standpoint, one should prefer f-strings to .format()
.
Best practices for clean and readable string interpolation
To ensure your string formatting is clear, efficient, and maintainable, follow these best practices when using interpolated strings.
- Prefer f-strings for readability (Python 3.6+)
# Recommended
name = "Alice"
age = 30
print(f"My name is {name} and I am {age} years old.")
# Not Recommended (Less readable)
print("My name is {} and I am {} years old.".format(name, age))
# Avoid using % formatting (Outdated)
print("My name is %s and I am %d years old." % (name, age))
My name is Alice and I am 30 years old.
My name is Alice and I am 30 years old.
My name is Alice and I am 30 years old.
- Use named placeholders for clarity
# Named placeholders (readable)
user = {"name": "Alice", "age": 30}
print(f"My name is {user['name']} and I am {user['age']} years old.")
# Using indexes in .format() (not as readable)
print("My name is {0} and I am {1} years old.".format("Alice", 30))
My name is Alice and I am 30 years old.
My name is Alice and I am 30 years old.
- Keep multiline strings readable.
name = "Alice"
age = 30
message = f"""Hello, {name}!
We are happy to invite you to our event.
At {age} years old, you are eligible for the VIP pass.
Best regards,
Event Team
"""
print(message)
Hello, Alice!
We are happy to invite you to our event.
At 30 years old, you are eligible for the VIP pass.
Best regards,
Event Team
- Use f-strings in Logging for Better Debugging
Python 3.8 and later supports =
for debugging in f-strings.
value = 42
# Output: value = 42
print(f"{value = }")
value = 42
Conclusion
String interpolation is a powerful feature in Python that makes string formatting cleaner, more readable, and more efficient. Among the available methods, f-strings are the most modern and recommended approach, offering better performance, clarity, and flexibility over older methods like .format()
and %
formatting.
By following best practices, such as using named placeholders, controlling decimal precision, aligning text for readability, and handling missing dictionary keys gracefully, you can write clean, professional, and maintainable string formatting in Python.
Whether you're generating formatted reports, multiline messages, or structured data outputs, f-strings provide a simple yet powerful way to integrate variables and expressions seamlessly. Embracing f-strings will not only improve your code quality but also enhance its efficiency.
For further information on Python string interpolation, check out DataCamp's resources:
- f-string Formatting in Python tutorial
- Python Append String: 6 Essential Concatenation Techniques
- Python Programming skill track
- Python Fundamentals skill track
- Introduction to Data Science in Python course
Learn Python From Scratch
Python String Interpolation FAQs
What is string interpolation in Python?
String interpolation is the process of inserting variables, expressions, or function outputs directly into a string. Python supports it using f-strings, .format(), and % formatting.
Are f-strings available in all Python versions?
No, f-strings were introduced in Python 3.6. If you're using an older version, you'll need to use .format() or % formatting instead.
Why are f-strings preferred over .format() and % formatting?
f-strings are faster, more readable, and more concise than .format() and % formatting. They allow direct variable embedding and inline expressions, making them more efficient.
Can I use f-strings with dictionaries?
Yes, you can access dictionary values inside f-strings:
user = {"name": "Alice", "age": 30}
print(f"My name is {user['name']} and I am {user['age']} years old.")
Alternatively, unpack the dictionary:
print(f"My name is {name} and I am {age}.".format(**user))
How do I format numbers using f-strings?
You can control decimal places and add thousands separators using format specifiers:
pi = 3.14159
print(f"Pi: {pi:.2f}")

Mark Pedigo, PhD, is a distinguished data scientist with expertise in healthcare data science, programming, and education. Holding a PhD in Mathematics, a B.S. in Computer Science, and a Professional Certificate in AI, Mark blends technical knowledge with practical problem-solving. His career includes roles in fraud detection, infant mortality prediction, and financial forecasting, along with contributions to NASA’s cost estimation software. As an educator, he has taught at DataCamp and Washington University in St. Louis and mentored junior programmers. In his free time, Mark enjoys Minnesota’s outdoors with his wife Mandy and dog Harley and plays jazz piano.
Top Python Courses
track
Python Programming Fundamentals
course
Introduction to Python
tutorial
Python Lambda Functions: A Beginner’s Guide
tutorial
Python Concatenate Strings Tutorial

DataCamp Team
5 min
tutorial
Python String Tutorial
tutorial
Python Tutorial for Beginners
tutorial