bpo-28626: rearrange discussion of output formatting to encourage f-strings (GH-6036)
The 'output formatting' section of the tutorial talks a lot about manual formatting with things like .rjust() and .zfill(), with only a passing reference to 3.6's new f-strings.
This doesn't drop all of the old material, but it does rearrange the topics into a more modern order: f-strings first, discussing formatting specifiers a bit; then calling .format(); finally manual formatting with .ljust().
(cherry picked from commit ced350b195
)
Co-authored-by: Andrew Kuchling <amk@amk.ca>
This commit is contained in:
parent
f5197ddfd0
commit
80a5f04592
|
@ -20,20 +20,39 @@ of file objects; the standard output file can be referenced as ``sys.stdout``.
|
||||||
See the Library Reference for more information on this.)
|
See the Library Reference for more information on this.)
|
||||||
|
|
||||||
Often you'll want more control over the formatting of your output than simply
|
Often you'll want more control over the formatting of your output than simply
|
||||||
printing space-separated values. There are two ways to format your output; the
|
printing space-separated values. There are several ways to format output.
|
||||||
first way is to do all the string handling yourself; using string slicing and
|
|
||||||
concatenation operations you can create any layout you can imagine. The
|
* To use :ref:`formatted string literals <tut-f-strings>`, begin a string
|
||||||
|
with ``f`` or ``F`` before the opening quotation mark or triple quotation mark.
|
||||||
|
Inside this string, you can write a Python expression between ``{`` and ``}``
|
||||||
|
characters that can refer to variables or literal values.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> year = 2016 ; event = 'Referendum'
|
||||||
|
>>> f'Results of the {year} {event}'
|
||||||
|
'Results of the 2016 Referendum'
|
||||||
|
|
||||||
|
* The :meth:`str.format` method of strings requires more manual
|
||||||
|
effort. You'll still use ``{`` and ``}`` to mark where a variable
|
||||||
|
will be substituted and can provide detailed formatting directives,
|
||||||
|
but you'll also need to provide the information to be formatted.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> yes_votes = 42_572_654 ; no_votes = 43_132_495
|
||||||
|
>>> percentage = (yes_votes/(yes_votes+no_votes)
|
||||||
|
>>> '{:-9} YES votes {:2.2%}'.format(yes_votes, percentage))
|
||||||
|
' 42572654 YES votes 49.67%'
|
||||||
|
|
||||||
|
* Finally, you can do all the string handling yourself by using string slicing and
|
||||||
|
concatenation operations to create any layout you can imagine. The
|
||||||
string type has some methods that perform useful operations for padding
|
string type has some methods that perform useful operations for padding
|
||||||
strings to a given column width; these will be discussed shortly. The second
|
strings to a given column width.
|
||||||
way is to use :ref:`formatted string literals <f-strings>`, or the
|
|
||||||
:meth:`str.format` method.
|
|
||||||
|
|
||||||
The :mod:`string` module contains a :class:`~string.Template` class which offers
|
When you don't need fancy output but just want a quick display of some
|
||||||
yet another way to substitute values into strings.
|
variables for debugging purposes, you can convert any value to a string with
|
||||||
|
the :func:`repr` or :func:`str` functions.
|
||||||
One question remains, of course: how do you convert values to strings? Luckily,
|
|
||||||
Python has ways to convert any value to a string: pass it to the :func:`repr`
|
|
||||||
or :func:`str` functions.
|
|
||||||
|
|
||||||
The :func:`str` function is meant to return representations of values which are
|
The :func:`str` function is meant to return representations of values which are
|
||||||
fairly human-readable, while :func:`repr` is meant to generate representations
|
fairly human-readable, while :func:`repr` is meant to generate representations
|
||||||
|
@ -67,60 +86,57 @@ Some examples::
|
||||||
... repr((x, y, ('spam', 'eggs')))
|
... repr((x, y, ('spam', 'eggs')))
|
||||||
"(32.5, 40000, ('spam', 'eggs'))"
|
"(32.5, 40000, ('spam', 'eggs'))"
|
||||||
|
|
||||||
Here are two ways to write a table of squares and cubes::
|
The :mod:`string` module contains a :class:`~string.Template` class that offers
|
||||||
|
yet another way to substitute values into strings, using placeholders like
|
||||||
|
``$x`` and replacing them with values from a dictionary, but offers much less
|
||||||
|
control of the formatting.
|
||||||
|
|
||||||
>>> for x in range(1, 11):
|
|
||||||
... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
|
.. _tut-f-strings:
|
||||||
... # Note use of 'end' on previous line
|
|
||||||
... print(repr(x*x*x).rjust(4))
|
Formatted String Literals
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
:ref:`Formatted string literals <f-strings>` (also called f-strings for
|
||||||
|
short) let you include the value of Python expressions inside a string by
|
||||||
|
prefixing the string with ``f`` or ``F`` and writing expressions as
|
||||||
|
``{expression}``.
|
||||||
|
|
||||||
|
An optional format specifier can follow the expression. This allows greater
|
||||||
|
control over how the value is formatted. The following example rounds pi to
|
||||||
|
three places after the decimal::
|
||||||
|
|
||||||
|
>>> import math
|
||||||
|
>>> print(f'The value of pi is approximately {math.pi:.3f}.')
|
||||||
|
|
||||||
|
Passing an integer after the ``':'`` will cause that field to be a minimum
|
||||||
|
number of characters wide. This is useful for making columns line up. ::
|
||||||
|
|
||||||
|
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
|
||||||
|
>>> for name, phone in table.items():
|
||||||
|
... print(f'{name:10} ==> {phone:10d}')
|
||||||
...
|
...
|
||||||
1 1 1
|
Sjoerd ==> 4127
|
||||||
2 4 8
|
Jack ==> 4098
|
||||||
3 9 27
|
Dcab ==> 7678
|
||||||
4 16 64
|
|
||||||
5 25 125
|
|
||||||
6 36 216
|
|
||||||
7 49 343
|
|
||||||
8 64 512
|
|
||||||
9 81 729
|
|
||||||
10 100 1000
|
|
||||||
|
|
||||||
>>> for x in range(1, 11):
|
Other modifiers can be used to convert the value before it is formatted.
|
||||||
... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
|
``'!a'`` applies :func:`ascii`, ``'!s'`` applies :func:`str`, and ``'!r'``
|
||||||
...
|
applies :func:`repr`::
|
||||||
1 1 1
|
|
||||||
2 4 8
|
|
||||||
3 9 27
|
|
||||||
4 16 64
|
|
||||||
5 25 125
|
|
||||||
6 36 216
|
|
||||||
7 49 343
|
|
||||||
8 64 512
|
|
||||||
9 81 729
|
|
||||||
10 100 1000
|
|
||||||
|
|
||||||
(Note that in the first example, one space between each column was added by the
|
>>> animals = 'eels'
|
||||||
way :func:`print` works: by default it adds spaces between its arguments.)
|
>>> print(f'My hovercraft is full of {animals}.')
|
||||||
|
My hovercraft is full of eels.
|
||||||
|
>>> print('My hovercraft is full of {animals !r}.')
|
||||||
|
My hovercraft is full of 'eels'.
|
||||||
|
|
||||||
This example demonstrates the :meth:`str.rjust` method of string
|
For a reference on these format specifications, see
|
||||||
objects, which right-justifies a string in a field of a given width by padding
|
the reference guide for the :ref:`formatspec`.
|
||||||
it with spaces on the left. There are similar methods :meth:`str.ljust` and
|
|
||||||
:meth:`str.center`. These methods do not write anything, they just return a
|
|
||||||
new string. If the input string is too long, they don't truncate it, but
|
|
||||||
return it unchanged; this will mess up your column lay-out but that's usually
|
|
||||||
better than the alternative, which would be lying about a value. (If you
|
|
||||||
really want truncation you can always add a slice operation, as in
|
|
||||||
``x.ljust(n)[:n]``.)
|
|
||||||
|
|
||||||
There is another method, :meth:`str.zfill`, which pads a numeric string on the
|
.. _tut-string-format:
|
||||||
left with zeros. It understands about plus and minus signs::
|
|
||||||
|
|
||||||
>>> '12'.zfill(5)
|
The String format() Method
|
||||||
'00012'
|
--------------------------
|
||||||
>>> '-3.14'.zfill(7)
|
|
||||||
'-003.14'
|
|
||||||
>>> '3.14159265359'.zfill(5)
|
|
||||||
'3.14159265359'
|
|
||||||
|
|
||||||
Basic usage of the :meth:`str.format` method looks like this::
|
Basic usage of the :meth:`str.format` method looks like this::
|
||||||
|
|
||||||
|
@ -150,34 +166,6 @@ Positional and keyword arguments can be arbitrarily combined::
|
||||||
other='Georg'))
|
other='Georg'))
|
||||||
The story of Bill, Manfred, and Georg.
|
The story of Bill, Manfred, and Georg.
|
||||||
|
|
||||||
``'!a'`` (apply :func:`ascii`), ``'!s'`` (apply :func:`str`) and ``'!r'``
|
|
||||||
(apply :func:`repr`) can be used to convert the value before it is formatted::
|
|
||||||
|
|
||||||
>>> contents = 'eels'
|
|
||||||
>>> print('My hovercraft is full of {}.'.format(contents))
|
|
||||||
My hovercraft is full of eels.
|
|
||||||
>>> print('My hovercraft is full of {!r}.'.format(contents))
|
|
||||||
My hovercraft is full of 'eels'.
|
|
||||||
|
|
||||||
An optional ``':'`` and format specifier can follow the field name. This allows
|
|
||||||
greater control over how the value is formatted. The following example
|
|
||||||
rounds Pi to three places after the decimal.
|
|
||||||
|
|
||||||
>>> import math
|
|
||||||
>>> print('The value of PI is approximately {0:.3f}.'.format(math.pi))
|
|
||||||
The value of PI is approximately 3.142.
|
|
||||||
|
|
||||||
Passing an integer after the ``':'`` will cause that field to be a minimum
|
|
||||||
number of characters wide. This is useful for making tables pretty. ::
|
|
||||||
|
|
||||||
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
|
|
||||||
>>> for name, phone in table.items():
|
|
||||||
... print('{0:10} ==> {1:10d}'.format(name, phone))
|
|
||||||
...
|
|
||||||
Jack ==> 4098
|
|
||||||
Dcab ==> 7678
|
|
||||||
Sjoerd ==> 4127
|
|
||||||
|
|
||||||
If you have a really long format string that you don't want to split up, it
|
If you have a really long format string that you don't want to split up, it
|
||||||
would be nice if you could reference the variables to be formatted by name
|
would be nice if you could reference the variables to be formatted by name
|
||||||
instead of by position. This can be done by simply passing the dict and using
|
instead of by position. This can be done by simply passing the dict and using
|
||||||
|
@ -198,10 +186,71 @@ notation. ::
|
||||||
This is particularly useful in combination with the built-in function
|
This is particularly useful in combination with the built-in function
|
||||||
:func:`vars`, which returns a dictionary containing all local variables.
|
:func:`vars`, which returns a dictionary containing all local variables.
|
||||||
|
|
||||||
|
As an example, the following lines produce a tidily-aligned
|
||||||
|
set of columns giving integers and their squares and cubes::
|
||||||
|
|
||||||
|
>>> for x in range(1, 11):
|
||||||
|
... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
|
||||||
|
...
|
||||||
|
1 1 1
|
||||||
|
2 4 8
|
||||||
|
3 9 27
|
||||||
|
4 16 64
|
||||||
|
5 25 125
|
||||||
|
6 36 216
|
||||||
|
7 49 343
|
||||||
|
8 64 512
|
||||||
|
9 81 729
|
||||||
|
10 100 1000
|
||||||
|
|
||||||
For a complete overview of string formatting with :meth:`str.format`, see
|
For a complete overview of string formatting with :meth:`str.format`, see
|
||||||
:ref:`formatstrings`.
|
:ref:`formatstrings`.
|
||||||
|
|
||||||
|
|
||||||
|
Manual String Formatting
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Here's the same table of squares and cubes, formatted manually::
|
||||||
|
|
||||||
|
>>> for x in range(1, 11):
|
||||||
|
... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
|
||||||
|
... # Note use of 'end' on previous line
|
||||||
|
... print(repr(x*x*x).rjust(4))
|
||||||
|
...
|
||||||
|
1 1 1
|
||||||
|
2 4 8
|
||||||
|
3 9 27
|
||||||
|
4 16 64
|
||||||
|
5 25 125
|
||||||
|
6 36 216
|
||||||
|
7 49 343
|
||||||
|
8 64 512
|
||||||
|
9 81 729
|
||||||
|
10 100 1000
|
||||||
|
|
||||||
|
(Note that the one space between each column was added by the
|
||||||
|
way :func:`print` works: it always adds spaces between its arguments.)
|
||||||
|
|
||||||
|
The :meth:`str.rjust` method of string objects right-justifies a string in a
|
||||||
|
field of a given width by padding it with spaces on the left. There are
|
||||||
|
similar methods :meth:`str.ljust` and :meth:`str.center`. These methods do
|
||||||
|
not write anything, they just return a new string. If the input string is too
|
||||||
|
long, they don't truncate it, but return it unchanged; this will mess up your
|
||||||
|
column lay-out but that's usually better than the alternative, which would be
|
||||||
|
lying about a value. (If you really want truncation you can always add a
|
||||||
|
slice operation, as in ``x.ljust(n)[:n]``.)
|
||||||
|
|
||||||
|
There is another method, :meth:`str.zfill`, which pads a numeric string on the
|
||||||
|
left with zeros. It understands about plus and minus signs::
|
||||||
|
|
||||||
|
>>> '12'.zfill(5)
|
||||||
|
'00012'
|
||||||
|
>>> '-3.14'.zfill(7)
|
||||||
|
'-003.14'
|
||||||
|
>>> '3.14159265359'.zfill(5)
|
||||||
|
'3.14159265359'
|
||||||
|
|
||||||
|
|
||||||
Old string formatting
|
Old string formatting
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
@ -211,8 +260,8 @@ to the right argument, and returns the string resulting from this formatting
|
||||||
operation. For example::
|
operation. For example::
|
||||||
|
|
||||||
>>> import math
|
>>> import math
|
||||||
>>> print('The value of PI is approximately %5.3f.' % math.pi)
|
>>> print('The value of pi is approximately %5.3f.' % math.pi)
|
||||||
The value of PI is approximately 3.142.
|
The value of pi is approximately 3.142.
|
||||||
|
|
||||||
More information can be found in the :ref:`old-string-formatting` section.
|
More information can be found in the :ref:`old-string-formatting` section.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue