Creating strings with formatted values
One of the basic abilities when dealing with creating text and documents is to be able to properly format values into structured strings. Python is smart at presenting good defaults, such as properly rendering a number, but there are a lot of options and possibilities.
We'll discuss some of the common options when creating formatted text using the example of a table.
Getting ready
The main tool to format strings in Python is the format
method. It works with a defined mini-language to render variables this way:
result = template.format(*parameters)
The template
is a string that is interpreted based on the mini-language. At its simplest, templating replaces the values between the curly brackets with the parameters. Here are a couple of examples:
>>> 'Put the value of the string here: {}'.format('STRING')
"Put the value of the string here: STRING"
>>> 'It can be any type ({}) and more than one ({})'.format(1.23, 'STRING')
"It can be any type (1.23) and more than one (STRING)"
>> 'Specify the order: {1}, {0}'.format('first', 'second')
'Specify the order: second, first'
>>> 'Or name parameters: {first}, {second}'.format(second='SECOND', first='FIRST')
'Or name parameters: FIRST, SECOND'
In 95% of cases, this formatting will be all that's required; keeping things simple is great! But for complicated times, such as when aligning strings automatically and creating good looking text tables, the mini-language format
has more options.
How to do it…
- Write the following script,
recipe_format_strings_step1.py
, to print an aligned table:# INPUT DATA data = [ (1000, 10), (2000, 17), (2500, 170), (2500, -170), ] # Print the header for reference print('REVENUE | PROFIT | PERCENT') # This template aligns and displays the data in the proper format TEMPLATE = '{revenue:>7,} | {profit:>+6} | {percent:>7.2%}' # Print the data rows for revenue, profit in data: row = TEMPLATE.format(revenue=revenue, profit=profit, percent=profit / revenue) print(row)
- Run it to display the following aligned table. Note that
PERCENT
is correctly displayed as a percentage:REVENUE | PROFIT | PERCENT 1,000 | +10 | 1.00% 2,000 | +17 | 0.85% 2,500 | +170 | 6.80% 2,500 | -170 | -6.80%
How it works…
The TEMPLATE
constant defines three columns, each one defined by a parameter named revenue
, profit
, and
percent
. This makes it explicit and straightforward to apply the template to the format
call.
After the name of the parameter, there's a colon that separates the format definition. Note that everything is inside the curly brackets. In all columns, the format specification sets the width to seven characters, to make sure all the columns have the same width, and aligns the values to the right with the > symbol:
revenue
adds a thousands separator with the,
symbol—[{revenue:>7,}]
.profit
adds a + sign for positive values. A - sign for negatives is added automatically—[{profit:>+7}]
.percent
displays a percent value with a precision of two decimal places—[{percent:>7.2%}]
. This is done through .2 (precision) and adding a % symbol for the percentage.
There's more…
You may have also seen the available Python formatting with the %
operator. While it works for simple formatting, it is less flexible than the formatted mini-language, and it is not recommended for use.
A great new feature since Python 3.6 is to use f
-strings, which perform a format action using defined variables:
>>> param1 = 'first'
>>> param2 = 'second'
>>> f'Parameters {param1}:{param2}'
'Parameters first:second'
This simplifies a lot of the code and allows us to create very descriptive and readable code.
Be careful when using f
-strings to ensure that the string is replaced at the proper time. A common problem is that the variable defined to be rendered is not yet defined. For example, TEMPLATE
, defined previously, won't be defined as an f-string, as revenue
and the rest of the parameters are not available at that point. All variables defined at the scope of the string definition will be available, both local and global.
If you need to write a curly bracket, you'll need to repeat it twice. Note that each duplication will be displayed as a single curly bracket, plus a curly bracket for the value replacement, making a total of three brackets:
>> value = 'VALUE'
>>> f'This is the value, in curly brackets {{{value}}}'
'This is the value, in curly brackets {VALUE}'
This allows us to create meta templates—templates that produce templates. In some cases, this will be useful, but they get complicated very quickly. Use with care, as it's easy to produce code that will be difficult to read.
Representing characters that have a special meaning usually requires some sort of special way to define them, for example, by duplicating the curly bracket like we see here. This is called "escaping" and it's a common process in any code representation.
The Python Format Specification mini-language has more options than the ones shown here.
As the language tries to be quite concise, sometimes it can be difficult to determine the position of the symbols. You may sometimes ask yourself questions, like "is the + symbol before or after the width parameters?" Read the documentation with care and remember to always include a colon before the format specification.
Please refer to the full documentation and examples on the Python then it would look like website: https://docs.python.org/3/library/string.html#formatspec or at this fantastic web page—https://pyformat.info—that shows lots of examples.
See also
- The Template Reports recipe in Chapter 5, Generating Fantastic Reports, to learn more advanced template techniques.
- The Manipulating strings recipe, covered later in this chapter, to learn more about working with text.