Fortunately, strings are not that complicated in Python.

String Formatting in Python

Antoine Ghilissen
6 min readAug 19, 2020

--

The good news is that there is only a handful of ways to handle string formatting in Python. Unfortunately there is no method-to-rule-them-all. Depending on what you need, the version of Python you are using, etc. a method will be more appropriate than another.

% operator

This way of formatting strings has always been available in Python and if you are familiar with the printf() function in C, it works in a very similar way. It might be the oldest method of string formatting, it is still a valid one and it hasn't been deprecated by the other methods, more recent. This being said be aware it comes with a warning note:

Note 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, the str.format() interface, or template strings may help avoid these errors. Each of these alternatives provides their own trade-offs and benefits of simplicity, flexibility, and/or extensibility. source

The Syntax

The syntax is pretty straight forward. You need to define your values and call them, with the % operator, into the desire output format:

>>> "%s %s!" % ('Hello', 'World')'Hello World!'

In this code, you can see:

  • "..." the formatted output string.
  • %s the specifiers % with their conversion flags: s.
  • % the string formatting operator.
  • (...) a tuple of values that need to be integrated in the output string.

This method offers some flexibility, as shown below:

>>> "Hello %(who)s ! This is %(which)03d example out of 
... the %(howmuch).2f ways to print strings in Python."
... % {'who': 'World', 'which': 1, 'howmuch': 4}

'Hello World ! This is 001 example out of the 4.00 ways to print strings in Python.'

In the code above, you will find the same structure as in the initial example but:

  • between the specifier % and its conversion flag, you will notice a mapping key: (...).
  • the tuple of values is replaced by a mapping dictionary (so the call is made on its keys).
  • here, the conversion flags are a little more complex and allow values formatting (.2f forces 2 digits after the period on a object converted as a float, for example).

The list of conversion flags can be found here.

Using the tuple variation of this method is great as a quick and easy way to generate a simple output but you can easily imagine how quickly readability plummets with an increase in output values. The mapping option should be preferred in that case.

Again, keep in mind that there are a number of cases where the % operator method won’t be returning the desired string (see the note at the beginning of the chapter).

str.format()

From Python 2.6 onwards the string module has been completed by the .format() method. It is a powerful way to format string. So powerful actually, it is considered a "Mini-Language". So I will only lay a primer for using this method.

The Syntax

Once again the syntax is rather simple, very similar to the % operator with output.format(values):

>>> "{} {}!".format('Hello', 'World')

'Hello World!'

The major difference here being that, although chained {} are read sequentially from the provided values (just as they would with %s), they are implicitly indexed. Would you do print("{1} {0}!".format('Hello', 'World'), the output would be World Hello!.

And to generate the same “complex” output as for the % operator:

>>> "Hello {who:s} ! This is {which:03d} example out of 
... the {howmuch:.2f} ways to print strings in Python.".format(
... who='World', which=2, howmuch=4)

'Hello World ! This is 002 example out of the 4.00 ways to print strings in Python.'

As you can see, mapping is also possible (by putting the key within the curly brackets {}) and formatting the output is achieved by adding the conversion flags :.2f, still within the curly brackets. Very similar to the % operator method. However, where str.format() outperforms % operator:

  • You can unpack a dictionary:
>>> dict = {'who': 'World', 'which': 2, 'howmuch': 4}
>>> "Hello {who:s} ! This is {which:03d} example out of the {howmuch:.2f} ways to print strings in Python.".format(**dict)

'Hello World ! This is 002 example out of the 4.00 ways to print strings in Python.'
  • You can access the values’ attributes:
>>> c = 3-5j # c is a complex number
>>> 'The complex number {0} is formed from the real part {0.real} and the imaginary part {0.imag}.'.format(c)

'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.'
  • You can access the values’ items:
>>> coord = (3, 5)
>>> 'X: {0[0]}; Y: {0[1]}'.format(coord)
X: 3; Y: 5

f-string

It is also called “Formatted String Literals” or “String Interpolation”. To use this method, you will need to use Python 3.6+.

The Syntax

The syntax is very similar to the previous 2 methods, except the values need to be declared before the f-string statement:

>>> word = 'World'
>>> f'Hello {word}!'

'Hello World!'

And for our complex example:

>>> who = 'World'
>>> which = 3
>>> howmuch = 4
>>> f"Hello {who:s} ! This is {which:03d} example out of the
... {howmuch:.2f} ways to print strings in Python."

'Hello World ! This is 003 example out of the 4.00 ways to print strings in Python.'

The conversion flags are the same and besides having to define the values before writing the statement, it is very similar to the str.format() method. So why bother with the f-string method?

Readability! Having the variables/values defined outside of the string statement makes the whole statement more succinct, more readable and therefore less prone to mistakes.

string.Template

The last method to format strings is a less powerful and the syntax is a little bit different but overall it is quite easy to use (if not easier).

>>> from string import Template
>>> t = Template('Hello $word!')
>>> t.substitute(word='World')

'Hello World!'

The downside of this method is the conversion will have to be done before hand as they can’t be handled by the Template() class. To reuse our 'complex' example we'd need to do something like the following:

>>> from string import Template
>>> t = Template ("Hello $who ! This is $which example out of the $howmuch ways to print strings in Python.")
>>> t.substitute(who = 'World', which = f'{4:03d}', howmuch = f'{4:.2f}')

'Hello World ! This is 004 example out of the 4.00 ways to print strings in Python.'

I hope you appreciate the irony of using an f-string to format the input of a str.Template()! :-)

Conclusion

I hope this quick tour of the various options of string formatting have helped you understand more about it. Generally speaking, I find the f-string method to be the suitable for most situations and I like how readable and how powerful its syntax is.

But as said earlier, it will really come down to what needs to be printed out. To be honest, I find myself using the % operator method quite often when a simple output is needed (e.g. in coding challenges).

Which ever method you use, I would strongly recommend to familiarise yourself with the conversion flags. They are used across the board and they are key to perfect your string output.

As a final note, here is another reason to prefer f-string: The execution times! This table shows f-string is the fastest method , followed by the % operator, then the str.format() and, finally the string.Template():

# code for timing the methods>>> import timeit
>>> timeit.timeit("""
>>> "Hello %(who)s ! This is %(which)03d example out of the %(howmuch).2f ways to print strings in Python." % \
>>> {'who': 'World', 'which': 1, 'howmuch': 4}
>>> """, number = 100000)

0.08852832200136618

>>> import timeit
>>> timeit.timeit("""
>>> "Hello {who:s} ! This is {which:03d} example out of the {howmuch:.2f} ways to print strings in Python."\
>>> .format(who='World', which=2, howmuch=4)
>>> """, number = 100000)

0.12318703200071468

>>> import timeit
>>> timeit.timeit("""
>>> who = 'World'
>>> which = 3
>>> howmuch = 4
>>> f"Hello {who:s} ! This is {which:03d} example out of the {howmuch:.2f} ways to print strings in Python."
>>> """, number = 100000)

0.07235609000053955

>>> import timeit
>>> timeit.timeit("""
>>> from string import Template
>>> t = Template ("Hello $who ! This is $which example out of the $howmuch ways to print strings in Python.")
>>> t.substitute(who = 'World', which = f'{4:03d}', howmuch = f'{4:.2f}')
>>> """, number = 100000)

0.4513537950006139

Useful links

--

--