As you have seen, basic string operations can be used to build nicely formatted output. This technique is useful for simple formatting, but building up a com
plex output through slicing and concatenation of smaller strings can be tedious.
Python provides a powerful string formatting operation that makes the job much easier. •
Let's start with a simple example. Here is a run of the change-counting program from Chapter 3:
Change Counter
Please enter the count of each coin type.
How many quarters do you have? 6 How many dimes do you have? 0
How many nickels do you have? 0 How many pennies do you have? 0
The total value of your change is 1.5
Notice that the final value is given as a fraction with only one decimal place.
This looks funny, since we expect the output to be something like
$1. 50.
We can fix this problem by changing the very last line of the program as follows:
print ( "The total value of your change is ${0 : 0.2f} " .format (total ) )
Now the program prints this message:
The total value of your change is $ 1 .50
Let's try to make some sense of this. The
f ormat
method is a built-in for Python strings. The idea is that the string serves as a sort of template, and values supplied as parameters are plugged into this template to form a new string. So string formatting takes the form:5.8. Input/Output as String Manipulation
<template-string >. format (<values >)
Curly braces (
{})
inside thetemplate-string
mark "slots" into which the provided
values
are inserted. The information inside the curly braces tells which value goes in the slot and how the value should be formatted. The Python formatting operator is very flexible. We will cover just some basics here; you can consult a Python reference if you'd like all of the details. In this book, the slot descriptions will always have the form:
{<index >: <format-specif ier >}
The
index
tells which of the parameters is inserted into the slot. 2 As usual in Python, indexing starts with 0. In the example above, there is a single slot and the index 0 is used to say that the first (and only) parameter is inserted into that slot.The part of the description after the colon specifies how the value should look when it is inserted into the slot. Again returning to the example, the format specifier is
0. 2f .
The format of this specifier is<width>. <precision ><type >.
The width specifies how many "spaces" the value should take up. If the value takes up less than the specified width, it is padded with extra characters (spaces are the default). If the value requires more space than allotted, it will take as much space as is required to show the value. So putting a 0 here essentially says "use as much space as you need." The precision is 2, which tells Python to round the value to two decimal places. Finally, the type character
f
says the value should be displayed as a fixed-point number. That means that the specified number of decimal places will always be shown, even if they are 0.A complete description of format specifiers is pretty hairy, but you can get a good handle on what's possible just by looking at a few examples. The simplest template strings just specify where to plug in the parameters.
>>> "Hello {0} {1}, you may have won ${2}".format("Mr.", "Smith", 10000) 'Hello Mr. Smith, you may have won $10000'
Often, you'll want to control the width and/ or precision of a numeric value.
>>> "This int, {0:5}, was placed in a field of width 5".format(7) 'This int, 7, was placed in a field of width 5'
>>> "This int, {0:10}, was placed in a field of width 10".format(7) 'This int, 7, was placed in a field of width 10'
2As of Python 3.1, the index portion of the slot description is optional. When the indexes are omitted, the parameters are just filled into the slots in a left-to-right fashion.
155
>>> "This float, {0:10.5}, has width 10 and precision 5".format(3.1415926) 'This float, 3.1416, has width 10 and precision 5'
>>> "This float, {0:10.5f}, is fixed at 5 decimal places".format(3.1415926)
'This float, 3.14159, is fixed at 5 decimal places'
>>> "This float, {0:0.5}, has width 0 and precision 5".format(3.1415926)
'This float, 3.1416, has width 0 and precision 5'
>>> "Compare {0} and {0:0.20}".format(3.14) 'Compare 3.14 and 3.1400000000000001243'
Notice that for normal (not fixed-point) floating-point numbers, the precision specifies the number of significant digits to print. For fixed-point (indicated by the
f
at the end of the specifier) the precision gives the number of decimal places. In the last example, the same number is printed out in two different formats. This illustrates that if you print enough digits of a floating-point number, you will almost always find a "surprise." The computer can't represent 3. 14 exactly as a floating-point number. The closest value it can represent is ever so slightly larger than 3. 14. If not given an explicit precision, Python will print the number out to a few decimal places. The slight extra amount shows up if you print lots of digits. Generally, Python only displays a closely rounded version of a float. Using explicit formatting allows you to see the full result down to the last bit.
You may notice that, by default, numeric values are right -justified. This is helpful for lining up numbers in columns. Strings, on the other hand, are left -justified in their fields. You can change the default behaviors by including an explicit justification character at the beginning of the format specifier. The necessary characters are <, >, and - for left, right, and center justification, respectively.
>>> " left j ustification : {0 : <5}" . format ( "Hi ! " ) 'left j ust if icat ion : Hi !
'>>> "right j ustif icat ion : {0 : >5} " . f ormat ( " Hi ! " ) 'right j ustification : Hi ! '
>>> " centered : {o : -5} " . f ormat ( " Hi ! " )
'centered : Hi ! '
5.8. Input/Output as String Manipulation