Skip to main content

A Guide to Python String Format Techniques

·1610 words·8 mins·
Python String Format F-Strings Drops
Author
Francisco Bustamante
A chemist working with Data Science and Python Programming.
Table of Contents

A significant part of our time is spent dealing with strings, so it is important to know how to present them in the desired way. This is what we will see in this article with several examples.

String formatting with % position markers
#

Way to format strings in Python. Currently, it is recommended to use the other forms presented later in the article. However, as there is still a lot of legacy code out there, it is important to know how to use it.

As the name suggests, position markers, such as %s, are used inside the string. For example:

print("A text will be put %s" % "here")
A text will be put here

When more than one insertion is needed, a tuple is passed with each insertion in the order it should appear in the string:

print("A text will be put %s, and %s" % ("here", "also here"))
A text will be put here, and also here

There are times when we need to pass a string that has meaning for the language interpreter, but we want the interpreter to treat it as a normal string. We call these cases raw strings. For example, \t in Python is the representation of the space of the TAB key. If we want it to be displayed literally \t instead of the space, we indicate with %r, where r is to indicate raw string:

print("Here is a TAB: \t. Now, its raw form: %r" % "\t")
Here is a TAB: 	. Now, its raw form: '\t'

Dealing with numbers
#

For a faithful representation of the number passed, use %s so that it is converted to a string. But manipulations can be made, such as truncation to an integer and showing the signal:

num = 13.744

print("Numbers as %s are converted to strings" % num)

print("They can also be represented as integers: %d; notice that there is no rounding" % num)

print("Showing the signal in integers: %+d" % num)
print("Showing the signal in floats: %+f" % num)
Numbers as 13.744 are converted to strings
They can also be represented as integers: 13; notice that there is no rounding
Showing the signal in integers: +13
Showing the signal in floats: +13.744000

See that the float representation had more decimals than the original number. We can modify this representation with the x.yf syntax, where x is the minimum number of characters and y, the decimal places:

print('Minimum of 5 characters with 2 decimal places: %5.2f' % num)
print('Minimum of 1 characters with 0 decimal places: %1.0f (notice the rounding)' % num)
print('Minimum of 1 characters with 5 decimal places: %1.5f' % num)
print('Minimum of 10 characters with 2 decimal places: %10.2f' % num)
print('Minimum of 10 characters with 2 decimal places: %+10.2f (with signal)' % num)
Minimum of 5 characters with 2 decimal places: 13.74
Minimum of 1 characters with 0 decimal places: 14 (notice the rounding)
Minimum of 1 characters with 5 decimal places: 13.74400
Minimum of 10 characters with 2 decimal places:      13.74
Minimum of 10 characters with 2 decimal places:     +13.74 (with signal)

Formatting with the format method
#

This was introduced in Python 3.0, and it is more flexible and legible than the previous method.

The format method is called on the string and the values to be inserted are passed as arguments. The position markers are indicated by curly braces {}.

For just one insertion:

print("It is going to be a text {}".format("here"))
It is going to be a text here

A great advantage of this method is to be able to pass the position of the insertion as well as the name of the variable:

print("Controling {2} {1}{0}".format("!", "order", "the"))

print("First: {a}; Second: {b}; Third: {c}".format(a=1, b="2", c=12.3))

print("The variable {p} can be reused: {p}.".format(p="(hi!)"))
Controling the order!
First: 1; Second: 2; Third: 12.3
The variable (hi!) can be reused: (hi!).

It is possible to use dictionaries to pass the values to be inserted through unpacking:

person = {"name": "Francisco", "age": 36}

print("Hello, {name}. You are {age} years old.".format(**person))
Hello, Francisco. You are 36 years old.

Alignment
#

With the format method, there were a great improvement in the alignment of the strings. The following example shows how to control the amount of space that the string will occupy:

print("{0:16} | {1:5}".format("Name", "Age"))
print("{0:16} | {1:5}".format("Alice", 33))
print("{0:16} | {1:5}".format("Bob", 42))
print("{0:16} | {1:5}".format("Charles", "69"))
Name             | Age  
Alice            |    33
Bob              |    42
Charles          | 69   

Note how the numeric values are aligned to the right by default, meanwhile the strings are aligned to the left. This can be changed by adding the alignment character before the number of spaces. For example, < for left alignment, > for right alignment, and ^ for center alignment:

print("{0:<8} | {1:^8} | {2:>8}".format("Left", "Center", "Right"))
print("{0:<8} | {1:^8} | {2:>8}".format(11, 22, 33))
Left     |  Center  |    Right
11       |    22    |       33

It is also possible to fill the empty spaces with a character of your choice:

print("{0:=<8} | {1:-^8} | {2:.>8}".format("Left", "Center", "Right"))
print("{0:=<8} | {1:-^8} | {2:.>8}".format(11, 22, 33))
Left==== | -Center- | ...Right
11====== | ---22--- | ......33

The alignment and width can be passed as parameters:

print('"{:{align}{width}}"'.format("text", align="^", width="10"))
"   text   "

Dealing with numbers
#

As with the % method, the format method can also deal with numbers. The syntax is similar, but with some novelties.

print("10 characters and 2 decimal places: {:10.2f}".format(13.579))
10 characters and 2 decimal places:      13.58

Now it is possible to control the distance from the signal to the number:

print("{:=5d}".format(-42))
print("{:=+5d}".format(42))
-  42
+  42

And it is also possible to use parameters:

print("10 characters and 2 decimal places: {:{sign}{width}.{prec}f}".format(13.579, sign="+", width=10, prec=2))
10 characters and 2 decimal places:     +13.58

Dealing with dates
#

The format method is also very useful for formatting dates created with the datetime module:

from datetime import datetime

print("{:%Y-%m-%d %H:%M}".format(datetime(1969, 7, 20, 22, 56)))
1969-07-20 22:56

You can have further information about the format method in the official documentation.

f-strings
#

From Python 3.6, f-strings were introduced, which are even more flexible and legible than the previous methods. The basic syntax is to put an f before the string and the variables to be inserted are passed inside curly braces {}:

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

The f-strings are solved at runtime, so it is possible to use expressions inside the curly braces:

print(f"Hello, {name.upper()}!")
Hello, ALICE!

Above, the upper method was called on the name variable. It is also possible to use mathematical operations:

print(f"{2 * 21}")
42

This is so simple and yet so powerful. Let’s create the multiplication table for the number 2 in three lines of code:

print("Multiplication table for 2:")

for i in range(11):
    print(f"2 x {i:2} = {2 * i:2}")
Multiplication table for 2:
2 x  0 =  0
2 x  1 =  2
2 x  2 =  4
2 x  3 =  6
2 x  4 =  8
2 x  5 = 10
2 x  6 = 12
2 x  7 = 14
2 x  8 = 16
2 x  9 = 18
2 x 10 = 20

Note that width and alignment instructions were passed to the f-string using the same syntax as the methods seen before. Two spaces were left for the numbers so that the table is well formatted.

Dealing with numbers
#

The syntax is the same as the previous methods, but with the f before the string:

num = 23.45

print("10 characters and 4 decimal places: {:10.4f} (format)".format(num))

print(f"10 characters and 4 decimal places: {num:10.4f} (f-string)")
10 characters and 4 decimal places:    23.4500 (format)
10 characters and 4 decimal places:    23.4500 (f-string)

Alignment
#

The syntax is the same as the previous methods, but with the f before the string. And we can take advantage of running expressions:

people = {
    "alice": {"name": "Alice Smith", "age": 24, "job": "engineer"},
    "bob": {"name": "Bob Stone", "age": 30, "job": "programmer"},
    "charles": {"name": "Charles Brown", "age": 25, "job": "designer"},
}

print(f"{"Name":^14} | {"Age":^5} | {"Job":^10}")
print(f"{"-"*14} | {"-"*5} | {"-"*10}")

for person in people:
    d = people[person]
    print(f"{d['name']:<14} | {d['age']:^5} | {d['job']:>10}")
     | Name          | Age | Job        |
     | ------------- | --- | ---------- |
     | Alice Smith   | 24  | engineer   |
     | Bob Stone     | 30  | programmer |
     | Charles Brown | 25  | designer   |

Dealing with dates
#

As with the previous methods, the f-strings are also very useful for formatting dates created with the datetime module:

now = datetime.now()

print(f"{now:%Y-%m-%d %H:%M}")
2024-04-09 21:00

You can have further information about f-strings in the official documentation.

What more can we do?
#

We saw how to format strings in Python using three different methods. The f-strings are the most recommended, as they are more flexible and legible. However, it is important to know the other methods, as there is still a lot of legacy code out there.

Even though we have seen a lot of examples, there is still a lot to explore. For example, we can format numbers as percentages, currencies, and dates in different formats. But the basics are already here, and with them, you can already do a lot. And remember, the best way to learn is by practicing. So, open your Python interpreter and start practicing!

I hope this article has been helpful to you. If you have any questions or suggestions, please leave them in the comments.

Did you like this article? It is part of Python Drops, a set of shorter posts focused on fundamentals of the Python language and programming in general. You can read more of these articles by searching for the “drops” tag here on the site.

Until next time!

Related

Generators in Python - Your Code 1000+ Times More Efficient
·1950 words·10 mins
Python Drops Performance Generators
Do you know the difference between a “normal” function and a generator function in Python? What is the difference between the return of a usual function and the yield of a generator? In this article we will answer these questions and also delve into some aspects of the language
Iterables vs Iterators in Python - Writing Efficient Code
·1414 words·7 mins
Python Drops Performance
Do you know what an iterable is? And an iterator? How to recognize these structures in Python? Answering these questions is the goal of this article.
Polynomial Manipulation with SymPy
·1486 words·7 mins
Python Sympy Math Polynomials
Certainly, one of the most abstract subjects in math classes: polynomials. After all, who has never been confused in a polynomial division, it is x everywhere. In this article, we will see how the SymPy library, for the Python language, helps us to deal with operations involving polynomials.