From 8d4bf9c9ca790070b91a01042d6ada5680047f3f Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 18 Apr 2025 16:03:05 +0100 Subject: [PATCH 1/6] Add overview of formatted string literals (f-strings) to ``str` Co-authored-by: Ezio Melotti Originally-authored-by: amaajemyfren@users.noreply.github.com --- Doc/library/stdtypes.rst | 130 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 48d179c270378c..67a62f6a365630 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2456,6 +2456,136 @@ expression support in the :mod:`re` module). '-0042' +.. index:: + single: ! formatted string literal + single: formatted string literals + single: ! f-string + single: f-strings + single: fstring + single: interpolated string literal + single: string; formatted literal + single: string; interpolated literal + single: {} (curly brackets); in formatted string literal + single: ! (exclamation mark); in formatted string literal + single: : (colon); in formatted string literal + single: = (equals); for help in debugging using string literals + +Formatted String Literals (f-strings) +------------------------------------- + +.. versionadded:: 3.6 + +An :dfn:`f-string` (formally a :dfn:`formatted string literal`) is +a string literal that is prefixed with ``f`` or ``F``. +This type of string literal allows embedding arbitrary Python expressions +within *replacement fields*, which are delimited by curly brackets (``{}``). +These expressions are evaluated at runtime, similarly to :meth:`str.format`, +and are converted into regular :class:`str` objects. +For example: + +.. code-block:: pycon + + >>> who = 'nobody' + >>> nationality = 'Spanish' + >>> f'{who.title()} expects the {nationality} Inquisition!' + 'Nobody expects the Spanish Inquisition!' + +It is also possible to use a multi line f-string: + +.. code-block:: pycon + + >>> f'''This is a string + ... on two lines''' + 'This is a string\non two lines' + +A single opening curly bracket, ``'{'``, marks a *replacement field* that +can contain any Python expression: + +.. code-block:: pycon + + >>> nationality = 'Spanish' + >>> f'The {name} Inquisition!' + 'The Spanish Inquisition!' + +To include a literal ``{`` or ``}``, use a double bracket: + +.. code-block:: pycon + + >>> x = 42 + >>> f'{{x}} is {x}' + '{x} is 42' + +Functions can also be used, and :ref:`format specifier `: + +.. code-block:: pycon + + >>> from math import sqrt + >>> f'√2 \N{ALMOST EQUAL TO} {sqrt(2):.5f}' + '√2 ≈ 1.41421' + +Any non-string expression is converted using :func:`str`, by default: + +.. code-block:: pycon + + >>> from fractions import Fraction + >>> f'{Fraction(1, 3)}' + '1/3' + +To use an explicit conversion, use the ``!`` (exclamation mark) operator, +followed by any of the valid formats, which are: + +========== ============== +Conversion Meaning +========== ============== +``!a`` :func:`ascii` +``!r`` :func:`repr` +``!s`` :func:`str` +========== ============== + +For example: + +.. code-block:: pycon + + >>> from fractions import Fraction + >>> f'{Fraction(1, 3)!s}' + '1/3' + >>> f'{Fraction(1, 3)!r}' + 'Fraction(1, 3)' + >>> question = '¿Dónde está el Presidente?' + >>> print(f'{question!a}') + '\xbfD\xf3nde est\xe1 el Presidente?' + +While debugging it may be helpful to see both the expression and its value, +using the equals sign (``=``) after the expression. +This preserves spaces within the brackets, and can be used with a converter. +By default, the debugging operator uses the :func:`repr` (``!r``) conversion. +For example: + +.. code-block:: pycon + + >>> from fractions import Fraction + >>> calculation = Fraction(1, 3) + >>> f'{calculation=}' + 'calculation=Fraction(1, 3)' + >>> f'{calculation = }' + 'calculation = Fraction(1, 3)' + >>> f'{calculation = !s}' + 'calculation = 1/3' + +Once the output has been evaluated, it can be formatted using a +:ref:`format specifier ` following a colon (``':'``). +After the expression has been evaluated, and possibly converted to a string, +the :meth:`__format__` method of the result is called with the format specifier, +or the empty string if no format specifier is given. +The formatted result is then used as the final value for the replacement field. +For example: + + >>> from fractions import Fraction + >>> f'{Fraction(1, 7):.6f}' + '0.142857' + >>> f'{Fraction(1, 7):_^+10}' + '___+1/7___' + .. _old-string-formatting: From 6558eb237f50e8af868f8cf7dfa045423251eda6 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 18 Apr 2025 16:26:04 +0100 Subject: [PATCH 2/6] Add more version changed notes --- Doc/library/dis.rst | 6 +++--- Doc/library/stdtypes.rst | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 4a5756b6ba24bf..44767b5dd2d5c9 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1667,7 +1667,7 @@ iterations of the loop. * ``oparg == 2``: call :func:`repr` on *value* * ``oparg == 3``: call :func:`ascii` on *value* - Used for implementing formatted literal strings (f-strings). + Used for implementing formatted string literals (f-strings). .. versionadded:: 3.13 @@ -1680,7 +1680,7 @@ iterations of the loop. result = value.__format__("") STACK.append(result) - Used for implementing formatted literal strings (f-strings). + Used for implementing formatted string literals (f-strings). .. versionadded:: 3.13 @@ -1693,7 +1693,7 @@ iterations of the loop. result = value.__format__(spec) STACK.append(result) - Used for implementing formatted literal strings (f-strings). + Used for implementing formatted string literals (f-strings). .. versionadded:: 3.13 diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 67a62f6a365630..dfc8c8a0cfba93 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2474,6 +2474,14 @@ Formatted String Literals (f-strings) ------------------------------------- .. versionadded:: 3.6 +.. versionchanged:: 3.7 + The :keyword:`await` and :keyword:`async for` can be used in expressions +within f-strings. +.. versionchanged:: 3.8 + Added the debugging operator (``=``) +.. versionchanged:: 3.12 + Many restrictions on expressions within f-strings have been removed. + Notably, nested strings, comments, and backslashes are now permitted. An :dfn:`f-string` (formally a :dfn:`formatted string literal`) is a string literal that is prefixed with ``f`` or ``F``. From ca8b6076be4c9755a9b99a869c5bbd525bcbcf9b Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 18 Apr 2025 16:37:50 +0100 Subject: [PATCH 3/6] fixup! Add more version changed notes --- Doc/library/stdtypes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index dfc8c8a0cfba93..01fe679c88b24e 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2476,7 +2476,7 @@ Formatted String Literals (f-strings) .. versionadded:: 3.6 .. versionchanged:: 3.7 The :keyword:`await` and :keyword:`async for` can be used in expressions -within f-strings. + within f-strings. .. versionchanged:: 3.8 Added the debugging operator (``=``) .. versionchanged:: 3.12 From e06ff6bd97e20717f6b3445ca02fc8dcbd12cf86 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sun, 20 Apr 2025 22:57:24 +0100 Subject: [PATCH 4/6] Resolve review --- Doc/library/stdtypes.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 01fe679c88b24e..2722af1eb96c39 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2512,7 +2512,7 @@ can contain any Python expression: .. code-block:: pycon >>> nationality = 'Spanish' - >>> f'The {name} Inquisition!' + >>> f'The {nationality} Inquisition!' 'The Spanish Inquisition!' To include a literal ``{`` or ``}``, use a double bracket: @@ -2583,11 +2583,13 @@ For example: Once the output has been evaluated, it can be formatted using a :ref:`format specifier ` following a colon (``':'``). After the expression has been evaluated, and possibly converted to a string, -the :meth:`__format__` method of the result is called with the format specifier, +the :meth:`!__format__` method of the result is called with the format specifier, or the empty string if no format specifier is given. The formatted result is then used as the final value for the replacement field. For example: +.. code-block:: pycon + >>> from fractions import Fraction >>> f'{Fraction(1, 7):.6f}' '0.142857' From 62af72295f4468b99d52fb06952a7bc2f260ce0d Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sun, 20 Apr 2025 22:58:46 +0100 Subject: [PATCH 5/6] Use doctest directives --- Doc/library/stdtypes.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 2722af1eb96c39..3c8177b73dc44c 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2491,7 +2491,7 @@ These expressions are evaluated at runtime, similarly to :meth:`str.format`, and are converted into regular :class:`str` objects. For example: -.. code-block:: pycon +.. doctest:: >>> who = 'nobody' >>> nationality = 'Spanish' @@ -2500,7 +2500,7 @@ For example: It is also possible to use a multi line f-string: -.. code-block:: pycon +.. doctest:: >>> f'''This is a string ... on two lines''' @@ -2509,7 +2509,7 @@ It is also possible to use a multi line f-string: A single opening curly bracket, ``'{'``, marks a *replacement field* that can contain any Python expression: -.. code-block:: pycon +.. doctest:: >>> nationality = 'Spanish' >>> f'The {nationality} Inquisition!' @@ -2517,7 +2517,7 @@ can contain any Python expression: To include a literal ``{`` or ``}``, use a double bracket: -.. code-block:: pycon +.. doctest:: >>> x = 42 >>> f'{{x}} is {x}' @@ -2525,7 +2525,7 @@ To include a literal ``{`` or ``}``, use a double bracket: Functions can also be used, and :ref:`format specifier `: -.. code-block:: pycon +.. doctest:: >>> from math import sqrt >>> f'√2 \N{ALMOST EQUAL TO} {sqrt(2):.5f}' @@ -2533,7 +2533,7 @@ Functions can also be used, and :ref:`format specifier `: Any non-string expression is converted using :func:`str`, by default: -.. code-block:: pycon +.. doctest:: >>> from fractions import Fraction >>> f'{Fraction(1, 3)}' @@ -2552,7 +2552,7 @@ Conversion Meaning For example: -.. code-block:: pycon +.. doctest:: >>> from fractions import Fraction >>> f'{Fraction(1, 3)!s}' @@ -2569,7 +2569,7 @@ This preserves spaces within the brackets, and can be used with a converter. By default, the debugging operator uses the :func:`repr` (``!r``) conversion. For example: -.. code-block:: pycon +.. doctest:: >>> from fractions import Fraction >>> calculation = Fraction(1, 3) @@ -2588,7 +2588,7 @@ or the empty string if no format specifier is given. The formatted result is then used as the final value for the replacement field. For example: -.. code-block:: pycon +.. doctest:: >>> from fractions import Fraction >>> f'{Fraction(1, 7):.6f}' From 99435810dbf183f13537c4cdf9f893ce7f3c536f Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 21 Apr 2025 08:39:20 +0100 Subject: [PATCH 6/6] Grammar --- Doc/library/stdtypes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 3c8177b73dc44c..39aaa5da0786f8 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2523,7 +2523,7 @@ To include a literal ``{`` or ``}``, use a double bracket: >>> f'{{x}} is {x}' '{x} is 42' -Functions can also be used, and :ref:`format specifier `: +Functions can also be used, and :ref:`format specifiers `: .. doctest:: @@ -2564,7 +2564,7 @@ For example: '\xbfD\xf3nde est\xe1 el Presidente?' While debugging it may be helpful to see both the expression and its value, -using the equals sign (``=``) after the expression. +by using the equals sign (``=``) after the expression. This preserves spaces within the brackets, and can be used with a converter. By default, the debugging operator uses the :func:`repr` (``!r``) conversion. For example: