String Formatting in Python 3


Strings, as you might already know, are sequences of characters, we can make use of them to communicate with the users of our programs, also to show our results in console or shell. In any case string formatting is required to produce really good-looking output, in this tutorial you'll learn how to do it using some new Python features and others old-fashioned.

Table of Content

logo

String Formatting in an old-fashioned way

In Python, there are multiple ways to format text strings, but before Python 3.6 there were only two main ones: the %-formatting operator and the str.format() method. Later in this Python version, Literal String Interpolation was introduced and called f-strings, we're going to talk more about them later. Also, there is a standard module called string which contains the template class which allows string interpolation too, we will cover this module in a next entry.

Now that you know the different alternatives you have to format strings, let's see the real Python formatting OG: the % operator.

The % operator

In Python, for string objects, the formatting operation is the only one built-in operation they have and is addressed with the % operator. Given 'string' % values, the instances of % in string are replaced with the values elements. We can use it as follows:

>>> "Hi! we are %s" % "The Python Tutor Team"
"Hi! we are The Python Tutor Team"

This operator allows you to do simple position formatting. Of course, you can use variables as well:

>>> team_name = "The Python Tutor Team"
>>> about = "our blog"
>>> "Hi! we are %s. What do you think about %s?" % (team_name, about)
"Hi! we are The Python Tutor Team. What do you think about our blog?"

This looks pretty cool, but it has a problem, the longer your string becomes, the less readable the code will be, check this out:

>>> language = "Python"
>>> teaches_me ="write clean code"
>>> where_to_use = "almost everything"
>>> area_1 = "Data Science"
>>> area_2 = "Machine Learning"
>>> area_3 = "Web Development"
>>> "%s is a great first programming language to learn, it teaches you to %s and you can use it in %s, from %s and %s to %s." % (language, teaches_me, where_to_use, area_1, area_2, area_3)
"Python is a great first programming language to learn, it teaches you to write clean code and you can use it in almost everything, from Data Science and Machine Learning to Web Development."

Now it doesn't look good right? This kind of formatting is a little verbose and it can be error-prone. Another problem is that %-formatting can't be used in tuples or dictionaries correctly:

>>> msg = ('Python Rocks!', 3.6)
>>> 'message: %s' % msg
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting

But we can address this as follows:

>>> msg = ('Python Rocks!', 3.6)
>>> 'message: %s' % (msg,)
"message: ('Python Rocks!', 3.6)"

Fortunately to address these problems the str.format() method was introduced. Let's see it!

The str.format() method

The "old-new way" to format strings came with the introduction of the str.format() method in Python 2.6. Since then, every string object in Python includes the build-in format method, which can take a "template" string and produce the same template but with some replacements. Check this out:

>>> "This is a {} blog about {}".format("great", "Python")
"This is a great blog about Python"

As you can see, we call the method in the string above, which has replacement fields delimited by braces {}. You can insert placeholders inside them from numeric index to variable names. If you don't specify anything, just like the example above, the method will assume the order of the replacements is the same as the braces in the string. Let's see some examples.

>>> "This is a {0} blog about {1}".format("great", "Python")
"This is a great blog about Python"

You can change the order the placeholders are filled:

>>> "This is a {1} blog about {0}".format("great", "Python")
"This is a Python blog about great"

As we mentioned you can also use variables:

>>> blog_name = "Python Tutor"
>>> topic = "Data Science"
>>> "The {} blog has great content about {}".format(blog_name, topic)
"The Python Tutor blog has great content about Data Science"

You can use keywords in the placeholders to be able to pass objects like tuples or dictionaries and fill the string with its values:

>>> posts = {'level':'advanced', 'topic': 'neural networks'} 
>>> "We will cover {level} topics like {topic}".format(level=posts['level'], topic=posts['topic'])
'We will cover advanced topics like neural networks'

We can use the * operator to unpack tuples:

>>> posts = ('advanced','neural networks') 
>>> "We will cover {} topics like {}".format(*posts)
'We will cover advanced topics like neural networks'

We can even use ** to unpack dictionaries and write less code:

>>> posts = {'level':'advanced', 'topic': 'neural networks'} 
>>> "We will cover {level} topics like {topic}".format(**posts)
'We will cover advanced topics like neural networks'

As we mentioned above, the str.format() was an upgrade of %-formatting, but is not perfect, it has the same problem of the % operator with longer strings and multiple parameters. A way to dealing with this and improve the code readability is using unpacking dictionaries as we just did.

Despite the improvement of the format method, the readability of the code was still in danger, but with Python 3.6 the f-strings came to the rescue.

String Formatting like a Rock Star using f-strings

The f-strings or literal strings are the easier way to format strings so far, as we said they were introduced in Python 3.6 with an intent to make simpler formatting string tasks. According to the PEP 498, the introduction of the f-strings does not propose to deprecate any other formatting mechanism, despite the fact they are either error-prone and inflexible.

As we can read in the Python docs, these kinds of strings have an f or F at the beginning and contain replacement fields inside curly braces {}. Looks pretty familiar right? Let's see f-strings in action so you can notice the differences.

>>> blog_name = "Python Tutor"
>>> topic = "Data Science"
>>> f"The {blog_name} blog has great content about {topic}"
"The Python Tutor blog has great content about Data Science"

See the difference now? The syntax is similar to the str.format() method but less wordy, in consequence, the code is much readable. Aren't you convinced enough? Looking at an example with a longer string will open your eyes:

>>> language = "Python"
>>> teaches_me ="write clean code"
>>> where_to_use = "almost everything"
>>> area_1 = "Data Science"
>>> area_2 = "Machine Learning"
>>> area_3 = "Web Development"
>>> f"{language} is a great first programming language to learn, it teaches you to {teaches_me} and you can use it in {where_to_use}, from {area_1} and {area_2} to {area_3}." 
"Python is a great first programming language to learn, it teaches you to write clean code and you can use it in almost everything, from Data Science and Machine Learning to Web Development."

Now we have a short and simpler code. BTW using the capital letter F outputs the same result:

>>> what = 'Python Rocks'
>>> F'Python what??... I said {what}!'
'Python what??... I said Python Rocks!'

One of the coolest features of f-strings is that they are evaluated at run time, so you can put in them any Python expression as follows:

>>> f'{5 * 5}'
'25'

You can call built-in methods inside them too, let's say you want to calculate the root square of 4 for some reason and print the result, using f-strings is pretty straightforward. Check this out:

>>> from math import sqrt
>>> print(f'{sqrt(4)}')
2.0

You could do the same with the format method but the code would be less readable. You can also use built-in string methods inside the curly braces:

>>> msg = 'I want this message in capital letters'
>>> f'{msg.upper()}'
'I WANT THIS MESSAGE IN CAPITAL LETTERS'

You can have multiline strings, which allows you to have more flexible and clean code. Let's see this example:

>>> language = "Python"
>>> teaches_me ="write clean code"
>>> where_to_use = "almost everything"
>>> area_1 = "Data Science"
>>> area_2 = "Machine Learning"
>>> area_3 = "Web Development"
>>> message = (
... f"{language} is a great first programming language to learn,"
... f" it teaches you to {teaches_me} and you can use it in {where_to_use},"
... f" from {area_1} and {area_2} to {area_3}."
... )
>>> message 
'Python is a great first programming language to learn, it teaches you to write clean code and you can use it in almost everything, from Data Science and Machine Learning to Web Development.'

Now, this code looks much understandable, isn't it? One last thing to remember is that if you don't put f before the string Python will print text with curly braces and variables:

>>> what = 'Python Rocks'
>>> print('Python what??... I said {what}!')
Python what??... I said {what}!

f-strings are pretty awesome, isn't it? But there's a bunch of stuff about them we didn't cover here, so we will in next entries. Now let's talk a little bit about when to use every of these formatting mechanisms.

Which one should you use?

At this point, it is clear you want your code to be as cleaner and understandable as possible. With this in mind, you should avoid the use of %-operator because its verbose syntaxes could lead you to cumbersome code and prone errors. In fact, the Python docs discourage its usage with the following 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."

On the other hand, choosing between str.format() method and the f-strings is not such clear since the PEP 498 does not propose to deprecate anything, as we can read in this extract:

"This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms."

One aspect you can take into account to make a decision is the speed: f-strings are faster than format method. This is because, as we mentioned f-strings are expressions evaluated in run time, here is a comparison:

>>> import timeit
>>> timeit.timeit("""what = "Python Rocks!"
... 'Python what??... I said {}'.format(what)""", number=10000)
0.007892299999980423
>>> timeit.timeit("""what = "Python Rocks!"
... f'Python what??... I said {what}'""", number=10000)
0.0029583000000457105

As you can see the f-strings are faster.

If performance is not a problem for you, we recommend choosing the method that simplifies your code, it could be circumstances where using format method could lead you to a more flexible code, who knows? Just remember The Zen of Python, Simple is better than complex.

In later entries we're going to go deeper into some cool features of f-strings and str.format() methods, so you will be able to produce awesome outputs. A Pythonist hug and keep in touch!.

2 Komentar

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel