Python String Formatting Best Practices – Real Python
Python String Formatting Best Practices – Real Python
Table of Contents
#1 “Old Style” String Formatting (% Operator)
#2 “New Style” String Formatting (str.format)
#3 String Interpolation / f-Strings (Python 3.6+)
#4 Template Strings (Standard Library)
Which String Formatting Method Should You Use?
Key Takeaways
Remove ads
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the
written tutorial to deepen your understanding: Python String Formatting Tips & Best Practices
Remember the Zen of Python and how there should be “one obvious way to do something in Python”? You might
scratch your head when you find out that there are four major ways to do string formatting in Python.
In this tutorial, you’ll learn the four main approaches to string formatting in Python, as well as their strengths and
weaknesses. You’ll also get a simple rule of thumb for how to pick the best general purpose string formatting
approach in your own programs.
Let’s jump right in, as we’ve got a lot to cover. In order to have a simple toy example for experimentation, let’s assume
you’ve got the following variables (or constants, really) to work with:
Help
Python >>>
Based on these variables, you’d like to generate an output string containing a simple error message:
Python >>>
That error could really spoil a dev’s Monday morning… But we’re here to discuss string formatting. So let’s get to
work.
Python >>>
I’m using the %s format specifier here to tell Python where to substitute the value of name, represented as a string.
There are other format specifiers available that let you control the output format. For example, it’s possible to convert
numbers to hexadecimal notation or add whitespace padding to generate nicely formatted tables and reports. (See
Python Docs: “printf-style String Formatting”.)
Here, you can use the %x format specifier to convert an int value to a string and to represent it as a hexadecimal
number:
Python >>>
The “old style” string formatting syntax changes slightly if you want to make multiple substitutions in a single string.
Because the % operator takes only one argument, you need to wrap the right-hand side in a tuple, like so:
Python >>>
It’s also possible to refer to variable substitutions by name in your format string, if you pass a mapping to the %
operator:
Python >>>
This makes your format strings easier to maintain and easier to modify in the future. You don’t have to worry about
making sure the order you’re passing in the values matches up with the order in which the values are referenced in
the format string. Of course, the downside is that this technique requires a little more typing.
I’m sure you’ve been wondering why this printf-style formatting is called “old style” string formatting. It was
technically superseded by “new style” formatting in Python 3, which we’re going to talk about next.
Remove ads
You can use format() to do simple positional formatting, just like you could with “old style” formatting:
Python >>>
Or, you can refer to your variable substitutions by name and use them in any order you want. This is quite a powerful
feature as it allows for re-arranging the order of display without changing the arguments passed to format():
Python >>>
This also shows that the syntax to format an int variable as a hexadecimal string has changed. Now you need to pass
a format spec by adding a :x suffix. The format string syntax has become more powerful without complicating the
simpler use cases. It pays off to read up on this string formatting mini-language in the Python documentation.
In Python 3, this “new style” string formatting is to be preferred over %-style formatting. While “old style” formatting
has been de-emphasized, it has not been deprecated. It is still supported in the latest versions of Python. According to
this discussion on the Python dev email list and this issue on the Python dev bug tracker, %-formatting is going to stick
around for a long time to come.
Still, the official Python 3 documentation doesn’t exactly recommend “old style” formatting or speak too fondly of it:
“The formatting operations described here exhibit a variety of quirks that lead to a number of common errors
(such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals or the
str.format() interface helps avoid these errors. These alternatives also provide more powerful, flexible and
extensible approaches to formatting text.” (Source)
This is why I’d personally try to stick with str.format for new code moving forward. Starting with Python 3.6, there’s
yet another way to format your strings. I’ll tell you all about it in the next section.
Python >>>
As you can see, this prefixes the string constant with the letter “f“—hence the name “f-strings.” This new formatting
syntax is powerful. Because you can embed arbitrary Python expressions, you can even do inline arithmetic with it.
Check out this example:
Python >>>
>>> a = 5
>>> b = 10
>>> f'Five plus ten is {a + b} and not {2 * (a + b)}.'
'Five plus ten is 15 and not 30.'
Formatted string literals are a Python parser feature that converts f-strings into a series of string constants and
expressions. They then get joined up to build the final string.
Imagine you had the following greet() function that contains an f-string:
Python >>>
When you disassemble the function and inspect what’s going on behind the scenes, you’ll see that the f-string in the
function gets transformed into something similar to the following:
Python >>>
The real implementation is slightly faster than that because it uses the BUILD_STRING opcode as an optimization. But
functionally they’re the same:
Python >>>
String literals also support the existing format string syntax of the str.format() method. That allows you to solve the
same formatting problems we’ve discussed in the previous two sections:
Python >>>
Python’s new formatted string literals are similar to JavaScript’s Template Literals added in ES2015. I think they’re
quite a nice addition to Python, and I’ve already started using them in my day to day (Python 3) work. You can learn
more about formatted string literals in our in-depth Python f-strings tutorial.
Remove ads
Python >>>
You see here that we need to import the Template class from Python’s built-in string module. Template strings are not
a core language feature but they’re supplied by the string module in the standard library.
Another difference is that template strings don’t allow format specifiers. So in order to get the previous error string
example to work, you’ll need to manually transform the int error number into a hex-string:
Python >>>
So when should you use template strings in your Python programs? In my opinion, the best time to use template
strings is when you’re handling formatted strings generated by users of your program. Due to their reduced
complexity, template strings are a safer choice.
The more complex formatting mini-languages of the other string formatting techniques might introduce security
vulnerabilities to your programs. For example, it’s possible for format strings to access arbitrary variables in your
program.
That means, if a malicious user can supply a format string, they can potentially leak secret keys and other sensitive
information! Here’s a simple proof of concept of how this attack might be used against your code:
Python >>>
See how a hypothetical attacker was able to extract our secret string by accessing the __globals__ dictionary from a
malicious format string? Scary, huh? Template strings close this attack vector. This makes them a safer choice if you’re
handling format strings generated from user input:
Python >>>
This flowchart is based on the rule of thumb that I apply when I’m writing Python:
Python String Formatting Rule of Thumb: If your format strings are user-supplied, use Template Strings (#4) to
avoid security issues. Otherwise, use Literal String Interpolation/f-Strings (#3) if you’re on Python 3.6+, and
“New Style” str.format (#2) if you’re not.
Key Takeaways
Perhaps surprisingly, there’s more than one way to handle string formatting in Python.
Each method has its individual pros and cons. Your use case will influence which method you should use.
If you’re having trouble deciding which string formatting method to use, try our Python String Formatting Rule of
Thumb.
Mark as Completed
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the
written tutorial to deepen your understanding: Python String Formatting Tips & Best Practices
🐍 Python Tricks 💌
Get a short & sweet Python Trick delivered to your inbox every couple of
days. No spam ever. Unsubscribe any time. Curated by the Real Python
team.
Email Address
Dan Bader is the owner and editor in chief of Real Python and the main developer of the
realpython.com learning platform. Dan has been writing code for more than 20 years and holds a
master's degree in computer science.
Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who
worked on this tutorial are:
Aldren Joanna
What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use?
Leave a comment below and let us know.
Commenting Tips: The most useful comments are those written with the goal of learning from or helping
out other students. Get tips for asking good questions and get answers to common questions in our
support portal.
Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours”
Live Q&A Session. Happy Pythoning!
Keep Learning
Recommended Video Course: Python String Formatting Tips & Best Practices
Remove ads