Skip to content

Commit aea5531

Browse files
encukoublaisepAA-TurnerStanFromIreland
authored
gh-135676: Reword the f-string (and t-string) section (GH-137469)
Much of the information was duplicated in stdtypes.rst; this PR keeps lexical/syntactical details in Lexical Analysis and the evaluation & runtime behaviour in Standard types, with cross-references between the two. Since the t-string section only listed differences from f-strings, and the grammar for the two is equivalent, that section was moved to Standard types almost entirely. Co-authored-by: Blaise Pabon <[email protected]> Co-authored-by: Adam Turner <[email protected]> Co-authored-by: Stan Ulbrych <[email protected]>
1 parent f6f456f commit aea5531

File tree

3 files changed

+332
-243
lines changed

3 files changed

+332
-243
lines changed

Doc/library/stdtypes.rst

Lines changed: 111 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2656,6 +2656,8 @@ expression support in the :mod:`re` module).
26562656
single: : (colon); in formatted string literal
26572657
single: = (equals); for help in debugging using string literals
26582658

2659+
.. _stdtypes-fstrings:
2660+
26592661
Formatted String Literals (f-strings)
26602662
-------------------------------------
26612663

@@ -2664,123 +2666,147 @@ Formatted String Literals (f-strings)
26642666
The :keyword:`await` and :keyword:`async for` can be used in expressions
26652667
within f-strings.
26662668
.. versionchanged:: 3.8
2667-
Added the debugging operator (``=``)
2669+
Added the debug specifier (``=``)
26682670
.. versionchanged:: 3.12
26692671
Many restrictions on expressions within f-strings have been removed.
26702672
Notably, nested strings, comments, and backslashes are now permitted.
26712673

26722674
An :dfn:`f-string` (formally a :dfn:`formatted string literal`) is
26732675
a string literal that is prefixed with ``f`` or ``F``.
2674-
This type of string literal allows embedding arbitrary Python expressions
2675-
within *replacement fields*, which are delimited by curly brackets (``{}``).
2676-
These expressions are evaluated at runtime, similarly to :meth:`str.format`,
2677-
and are converted into regular :class:`str` objects.
2678-
For example:
2676+
This type of string literal allows embedding the results of arbitrary Python
2677+
expressions within *replacement fields*, which are delimited by curly
2678+
brackets (``{}``).
2679+
Each replacement field must contain an expression, optionally followed by:
26792680

2680-
.. doctest::
2681+
* a *debug specifier* -- an equal sign (``=``);
2682+
* a *conversion specifier* -- ``!s``, ``!r`` or ``!a``; and/or
2683+
* a *format specifier* prefixed with a colon (``:``).
26812684

2682-
>>> who = 'nobody'
2683-
>>> nationality = 'Spanish'
2684-
>>> f'{who.title()} expects the {nationality} Inquisition!'
2685-
'Nobody expects the Spanish Inquisition!'
2685+
See the :ref:`Lexical Analysis section on f-strings <f-strings>` for details
2686+
on the syntax of these fields.
26862687

2687-
It is also possible to use a multi line f-string:
2688+
Debug specifier
2689+
^^^^^^^^^^^^^^^
26882690

2689-
.. doctest::
2691+
.. versionadded:: 3.8
26902692

2691-
>>> f'''This is a string
2692-
... on two lines'''
2693-
'This is a string\non two lines'
2693+
If a debug specifier -- an equal sign (``=``) -- appears after the replacement
2694+
field expression, the resulting f-string will contain the expression's source,
2695+
the equal sign, and the value of the expression.
2696+
This is often useful for debugging::
26942697

2695-
A single opening curly bracket, ``'{'``, marks a *replacement field* that
2696-
can contain any Python expression:
2698+
>>> number = 14.3
2699+
>>> f'{number=}'
2700+
'number=14.3'
26972701

2698-
.. doctest::
2699-
2700-
>>> nationality = 'Spanish'
2701-
>>> f'The {nationality} Inquisition!'
2702-
'The Spanish Inquisition!'
2702+
Whitespace before, inside and after the expression, as well as whitespace
2703+
after the equal sign, is significant --- it is retained in the result::
27032704

2704-
To include a literal ``{`` or ``}``, use a double bracket:
2705+
>>> f'{ number - 4 = }'
2706+
' number - 4 = 10.3'
27052707

2706-
.. doctest::
27072708

2708-
>>> x = 42
2709-
>>> f'{{x}} is {x}'
2710-
'{x} is 42'
2709+
Conversion specifier
2710+
^^^^^^^^^^^^^^^^^^^^
27112711

2712-
Functions can also be used, and :ref:`format specifiers <formatstrings>`:
2713-
2714-
.. doctest::
2715-
2716-
>>> from math import sqrt
2717-
>>> f'√2 \N{ALMOST EQUAL TO} {sqrt(2):.5f}'
2718-
'√2 ≈ 1.41421'
2719-
2720-
Any non-string expression is converted using :func:`str`, by default:
2721-
2722-
.. doctest::
2712+
By default, the value of a replacement field expression is converted to
2713+
a string using :func:`str`::
27232714

27242715
>>> from fractions import Fraction
2725-
>>> f'{Fraction(1, 3)}'
2716+
>>> one_third = Fraction(1, 3)
2717+
>>> f'{one_third}'
27262718
'1/3'
27272719

2728-
To use an explicit conversion, use the ``!`` (exclamation mark) operator,
2729-
followed by any of the valid formats, which are:
2720+
When a debug specifier but no format specifier is used, the default conversion
2721+
instead uses :func:`repr`::
27302722

2731-
========== ==============
2732-
Conversion Meaning
2733-
========== ==============
2734-
``!a`` :func:`ascii`
2735-
``!r`` :func:`repr`
2736-
``!s`` :func:`str`
2737-
========== ==============
2723+
>>> f'{one_third = }'
2724+
'one_third = Fraction(1, 3)'
27382725

2739-
For example:
2726+
The conversion can be specified explicitly using one of these specifiers:
27402727

2741-
.. doctest::
2728+
* ``!s`` for :func:`str`
2729+
* ``!r`` for :func:`repr`
2730+
* ``!a`` for :func:`ascii`
27422731

2743-
>>> from fractions import Fraction
2744-
>>> f'{Fraction(1, 3)!s}'
2732+
For example::
2733+
2734+
>>> str(one_third)
27452735
'1/3'
2746-
>>> f'{Fraction(1, 3)!r}'
2736+
>>> repr(one_third)
27472737
'Fraction(1, 3)'
2748-
>>> question = '¿Dónde está el Presidente?'
2749-
>>> print(f'{question!a}')
2750-
'\xbfD\xf3nde est\xe1 el Presidente?'
2751-
2752-
While debugging it may be helpful to see both the expression and its value,
2753-
by using the equals sign (``=``) after the expression.
2754-
This preserves spaces within the brackets, and can be used with a converter.
2755-
By default, the debugging operator uses the :func:`repr` (``!r``) conversion.
2756-
For example:
27572738

2758-
.. doctest::
2739+
>>> f'{one_third!s} is {one_third!r}'
2740+
'1/3 is Fraction(1, 3)'
27592741

2760-
>>> from fractions import Fraction
2761-
>>> calculation = Fraction(1, 3)
2762-
>>> f'{calculation=}'
2763-
'calculation=Fraction(1, 3)'
2764-
>>> f'{calculation = }'
2765-
'calculation = Fraction(1, 3)'
2766-
>>> f'{calculation = !s}'
2767-
'calculation = 1/3'
2768-
2769-
Once the output has been evaluated, it can be formatted using a
2770-
:ref:`format specifier <formatstrings>` following a colon (``':'``).
2771-
After the expression has been evaluated, and possibly converted to a string,
2772-
the :meth:`!__format__` method of the result is called with the format specifier,
2773-
or the empty string if no format specifier is given.
2774-
The formatted result is then used as the final value for the replacement field.
2775-
For example:
2742+
>>> string = "¡kočka 😸!"
2743+
>>> ascii(string)
2744+
"'\\xa1ko\\u010dka \\U0001f638!'"
27762745

2777-
.. doctest::
2746+
>>> f'{string = !a}'
2747+
"string = '\\xa1ko\\u010dka \\U0001f638!'"
2748+
2749+
2750+
Format specifier
2751+
^^^^^^^^^^^^^^^^
2752+
2753+
After the expression has been evaluated, and possibly converted using an
2754+
explicit conversion specifier, it is formatted using the :func:`format` function.
2755+
If the replacement field includes a *format specifier* introduced by a colon
2756+
(``:``), the specifier is passed to :func:`!format` as the second argument.
2757+
The result of :func:`!format` is then used as the final value for the
2758+
replacement field. For example::
27782759

27792760
>>> from fractions import Fraction
2780-
>>> f'{Fraction(1, 7):.6f}'
2781-
'0.142857'
2782-
>>> f'{Fraction(1, 7):_^+10}'
2783-
'___+1/7___'
2761+
>>> one_third = Fraction(1, 3)
2762+
>>> f'{one_third:.6f}'
2763+
'0.333333'
2764+
>>> f'{one_third:_^+10}'
2765+
'___+1/3___'
2766+
>>> >>> f'{one_third!r:_^20}'
2767+
'___Fraction(1, 3)___'
2768+
>>> f'{one_third = :~>10}~'
2769+
'one_third = ~~~~~~~1/3~'
2770+
2771+
.. _stdtypes-tstrings:
2772+
2773+
Template String Literals (t-strings)
2774+
------------------------------------
2775+
2776+
An :dfn:`t-string` (formally a :dfn:`template string literal`) is
2777+
a string literal that is prefixed with ``t`` or ``T``.
2778+
2779+
These strings follow the same syntax and evaluation rules as
2780+
:ref:`formatted string literals <stdtypes-fstrings>`,
2781+
with for the following differences:
2782+
2783+
* Rather than evaluating to a ``str`` object, template string literals evaluate
2784+
to a :class:`string.templatelib.Template` object.
2785+
2786+
* The :func:`format` protocol is not used.
2787+
Instead, the format specifier and conversions (if any) are passed to
2788+
a new :class:`~string.templatelib.Interpolation` object that is created
2789+
for each evaluated expression.
2790+
It is up to code that processes the resulting :class:`~string.templatelib.Template`
2791+
object to decide how to handle format specifiers and conversions.
2792+
2793+
* Format specifiers containing nested replacement fields are evaluated eagerly,
2794+
prior to being passed to the :class:`~string.templatelib.Interpolation` object.
2795+
For instance, an interpolation of the form ``{amount:.{precision}f}`` will
2796+
evaluate the inner expression ``{precision}`` to determine the value of the
2797+
``format_spec`` attribute.
2798+
If ``precision`` were to be ``2``, the resulting format specifier
2799+
would be ``'.2f'``.
2800+
2801+
* When the equals sign ``'='`` is provided in an interpolation expression,
2802+
the text of the expression is appended to the literal string that precedes
2803+
the relevant interpolation.
2804+
This includes the equals sign and any surrounding whitespace.
2805+
The :class:`!Interpolation` instance for the expression will be created as
2806+
normal, except that :attr:`~string.templatelib.Interpolation.conversion` will
2807+
be set to '``r``' (:func:`repr`) by default.
2808+
If an explicit conversion or format specifier are provided,
2809+
this will override the default behaviour.
27842810

27852811

27862812
.. _old-string-formatting:

Doc/reference/expressions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Formally:
174174
.. grammar-snippet::
175175
:group: python-grammar
176176

177-
strings: ( `STRING` | fstring)+ | tstring+
177+
strings: ( `STRING` | `fstring`)+ | `tstring`+
178178

179179
This feature is defined at the syntactical level, so it only works with literals.
180180
To concatenate string expressions at run time, the '+' operator may be used::

0 commit comments

Comments
 (0)