CINXE.COM

PEP 498 – Literal String Interpolation | peps.python.org

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 498 – Literal String Interpolation | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0498/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 498 – Literal String Interpolation | peps.python.org'> <meta property="og:description" content="Python supports multiple ways to format text strings. These include %-formatting 1, str.format() 2, and string.Template 3. Each of these methods have their advantages, but in addition have disadvantages that make them cumbersome to use in practice. This..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0498/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="Python supports multiple ways to format text strings. These include %-formatting 1, str.format() 2, and string.Template 3. Each of these methods have their advantages, but in addition have disadvantages that make them cumbersome to use in practice. This..."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li> <li><a href="../pep-0000/">PEP Index</a> &raquo; </li> <li>PEP 498</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 498 – Literal String Interpolation</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Eric V. Smith &lt;eric&#32;&#97;t&#32;trueblade.com&gt;</dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">01-Aug-2015</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">3.6</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even">07-Aug-2015, 30-Aug-2015, 04-Sep-2015, 19-Sep-2015, 06-Nov-2016</dd> <dt class="field-odd">Resolution<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-September/141526.html">Python-Dev message</a></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#no-use-of-globals-or-locals">No use of globals() or locals()</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#escape-sequences">Escape sequences</a></li> <li><a class="reference internal" href="#code-equivalence">Code equivalence</a></li> <li><a class="reference internal" href="#expression-evaluation">Expression evaluation</a></li> <li><a class="reference internal" href="#format-specifiers">Format specifiers</a></li> <li><a class="reference internal" href="#concatenating-strings">Concatenating strings</a></li> <li><a class="reference internal" href="#error-handling">Error handling</a></li> <li><a class="reference internal" href="#leading-and-trailing-whitespace-in-expressions-is-ignored">Leading and trailing whitespace in expressions is ignored</a></li> <li><a class="reference internal" href="#evaluation-order-of-expressions">Evaluation order of expressions</a></li> </ul> </li> <li><a class="reference internal" href="#discussion">Discussion</a><ul> <li><a class="reference internal" href="#python-ideas-discussion">python-ideas discussion</a><ul> <li><a class="reference internal" href="#how-to-denote-f-strings">How to denote f-strings</a></li> <li><a class="reference internal" href="#how-to-specify-the-location-of-expressions-in-f-strings">How to specify the location of expressions in f-strings</a></li> <li><a class="reference internal" href="#supporting-full-python-expressions">Supporting full Python expressions</a></li> </ul> </li> <li><a class="reference internal" href="#similar-support-in-other-languages">Similar support in other languages</a></li> <li><a class="reference internal" href="#differences-between-f-string-and-str-format-expressions">Differences between f-string and str.format expressions</a></li> <li><a class="reference internal" href="#triple-quoted-f-strings">Triple-quoted f-strings</a></li> <li><a class="reference internal" href="#raw-f-strings">Raw f-strings</a></li> <li><a class="reference internal" href="#no-binary-f-strings">No binary f-strings</a></li> <li><a class="reference internal" href="#s-r-and-a-are-redundant"><code class="docutils literal notranslate"><span class="pre">!s</span></code>, <code class="docutils literal notranslate"><span class="pre">!r</span></code>, and <code class="docutils literal notranslate"><span class="pre">!a</span></code> are redundant</a></li> <li><a class="reference internal" href="#lambdas-inside-expressions">Lambdas inside expressions</a></li> <li><a class="reference internal" href="#can-t-combine-with-u">Can’t combine with ‘u’</a></li> </ul> </li> <li><a class="reference internal" href="#examples-from-python-s-source-code">Examples from Python’s source code</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>Python supports multiple ways to format text strings. These include %-formatting <a class="footnote-reference brackets" href="#id11" id="id1">[1]</a>, <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> <a class="footnote-reference brackets" href="#id12" id="id2">[2]</a>, and <code class="docutils literal notranslate"><span class="pre">string.Template</span></code> <a class="footnote-reference brackets" href="#id13" id="id3">[3]</a>. Each of these methods have their advantages, but in addition have disadvantages that make them cumbersome to use in practice. This PEP proposed to add a new string formatting mechanism: Literal String Interpolation. In this PEP, such strings will be referred to as “f-strings”, taken from the leading character used to denote such strings, and standing for “formatted strings”.</p> <p>This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms.</p> <p>F-strings provide a way to embed expressions inside string literals, using a minimal syntax. It should be noted that an f-string is really an expression evaluated at run time, not a constant value. In Python source code, an f-string is a literal string, prefixed with ‘f’, which contains expressions inside braces. The expressions are replaced with their values. Some examples are:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">datetime</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">name</span> <span class="o">=</span> <span class="s1">&#39;Fred&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">age</span> <span class="o">=</span> <span class="mi">50</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">anniversary</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">1991</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;My name is </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s1">, my age next year is </span><span class="si">{</span><span class="n">age</span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s1">, my anniversary is </span><span class="si">{</span><span class="n">anniversary</span><span class="si">:</span><span class="s1">%A, %B %d, %Y</span><span class="si">}</span><span class="s1">.&#39;</span> <span class="go">&#39;My name is Fred, my age next year is 51, my anniversary is Saturday, October 12, 1991.&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;He said his name is </span><span class="si">{</span><span class="n">name</span><span class="si">!r}</span><span class="s1">.&#39;</span> <span class="go">&quot;He said his name is &#39;Fred&#39;.&quot;</span> </pre></div> </div> <p>A similar feature was proposed in <a class="pep reference internal" href="../pep-0215/" title="PEP 215 – String Interpolation">PEP 215</a>. <a class="pep reference internal" href="../pep-0215/" title="PEP 215 – String Interpolation">PEP 215</a> proposed to support a subset of Python expressions, and did not support the type-specific string formatting (the <code class="docutils literal notranslate"><span class="pre">__format__()</span></code> method) which was introduced with <a class="pep reference internal" href="../pep-3101/" title="PEP 3101 – Advanced String Formatting">PEP 3101</a>.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>This PEP is driven by the desire to have a simpler way to format strings in Python. The existing ways of formatting are either error prone, inflexible, or cumbersome.</p> <p>%-formatting is limited as to the types it supports. Only ints, strs, and doubles can be formatted. All other types are either not supported, or converted to one of these types before formatting. In addition, there’s a well-known trap where a single value is passed:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">msg</span> <span class="o">=</span> <span class="s1">&#39;disk failure&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;error: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">msg</span> <span class="go">&#39;error: disk failure&#39;</span> </pre></div> </div> <p>But if msg were ever to be a tuple, the same code would fail:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">msg</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;disk failure&#39;</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;error: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">msg</span> <span class="gt">Traceback (most recent call last):</span> File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span> <span class="gr">TypeError</span>: <span class="n">not all arguments converted during string formatting</span> </pre></div> </div> <p>To be defensive, the following code should be used:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;error: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">msg</span><span class="p">,)</span> <span class="go">&quot;error: (&#39;disk failure&#39;, 32)&quot;</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">str.format()</span></code> was added to address some of these problems with %-formatting. In particular, it uses normal function call syntax (and therefore supports multiple parameters) and it is extensible through the <code class="docutils literal notranslate"><span class="pre">__format__()</span></code> method on the object being converted to a string. See <a class="pep reference internal" href="../pep-3101/" title="PEP 3101 – Advanced String Formatting">PEP 3101</a> for a detailed rationale. This PEP reuses much of the <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> syntax and machinery, in order to provide continuity with an existing Python string formatting mechanism.</p> <p>However, <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> is not without its issues. Chief among them is its verbosity. For example, the text <code class="docutils literal notranslate"><span class="pre">value</span></code> is repeated here:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">value</span> <span class="o">=</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">20</span> <span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;The value is </span><span class="si">{value}</span><span class="s1">.&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="n">value</span><span class="p">)</span> <span class="go">&#39;The value is 80.&#39;</span> </pre></div> </div> <p>Even in its simplest form there is a bit of boilerplate, and the value that’s inserted into the placeholder is sometimes far removed from where the placeholder is situated:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;The value is </span><span class="si">{}</span><span class="s1">.&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="go">&#39;The value is 80.&#39;</span> </pre></div> </div> <p>With an f-string, this becomes:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;The value is </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s1">.&#39;</span> <span class="go">&#39;The value is 80.&#39;</span> </pre></div> </div> <p>F-strings provide a concise, readable way to include the value of Python expressions inside strings.</p> <p>In this sense, <code class="docutils literal notranslate"><span class="pre">string.Template</span></code> and %-formatting have similar shortcomings to <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>, but also support fewer formatting options. In particular, they do not support the <code class="docutils literal notranslate"><span class="pre">__format__</span></code> protocol, so that there is no way to control how a specific object is converted to a string, nor can it be extended to additional types that want to control how they are converted to strings (such as <code class="docutils literal notranslate"><span class="pre">Decimal</span></code> and <code class="docutils literal notranslate"><span class="pre">datetime</span></code>). This example is not possible with <code class="docutils literal notranslate"><span class="pre">string.Template</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">value</span> <span class="o">=</span> <span class="mi">1234</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;input=</span><span class="si">{</span><span class="n">value</span><span class="si">:</span><span class="s1">#06x</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;input=0x04d2&#39;</span> </pre></div> </div> <p>And neither %-formatting nor <code class="docutils literal notranslate"><span class="pre">string.Template</span></code> can control formatting such as:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">date</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">1991</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">date</span><span class="si">}</span><span class="s1"> was on a </span><span class="si">{</span><span class="n">date</span><span class="si">:</span><span class="s1">%A</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;1991-10-12 was on a Saturday&#39;</span> </pre></div> </div> <section id="no-use-of-globals-or-locals"> <h3><a class="toc-backref" href="#no-use-of-globals-or-locals" role="doc-backlink">No use of globals() or locals()</a></h3> <p>In the discussions on python-dev <a class="footnote-reference brackets" href="#id14" id="id4">[4]</a>, a number of solutions where presented that used locals() and globals() or their equivalents. All of these have various problems. Among these are referencing variables that are not otherwise used in a closure. Consider:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span><span class="w"> </span><span class="nf">outer</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="gp">... </span> <span class="k">def</span><span class="w"> </span><span class="nf">inner</span><span class="p">():</span> <span class="gp">... </span> <span class="k">return</span> <span class="s1">&#39;x=</span><span class="si">{x}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format_map</span><span class="p">(</span><span class="nb">locals</span><span class="p">())</span> <span class="gp">... </span> <span class="k">return</span> <span class="n">inner</span> <span class="gp">...</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">outer</span><span class="p">(</span><span class="mi">42</span><span class="p">)()</span> <span class="gt">Traceback (most recent call last):</span> File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span> File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">3</span>, in <span class="n">inner</span> <span class="gr">KeyError</span>: <span class="n">&#39;x&#39;</span> </pre></div> </div> <p>This returns an error because the compiler has not added a reference to x inside the closure. You need to manually add a reference to x in order for this to work:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span><span class="w"> </span><span class="nf">outer</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="gp">... </span> <span class="k">def</span><span class="w"> </span><span class="nf">inner</span><span class="p">():</span> <span class="gp">... </span> <span class="n">x</span> <span class="gp">... </span> <span class="k">return</span> <span class="s1">&#39;x=</span><span class="si">{x}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format_map</span><span class="p">(</span><span class="nb">locals</span><span class="p">())</span> <span class="gp">... </span> <span class="k">return</span> <span class="n">inner</span> <span class="gp">...</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">outer</span><span class="p">(</span><span class="mi">42</span><span class="p">)()</span> <span class="go">&#39;x=42&#39;</span> </pre></div> </div> <p>In addition, using locals() or globals() introduces an information leak. A called routine that has access to the callers locals() or globals() has access to far more information than needed to do the string interpolation.</p> <p>Guido stated <a class="footnote-reference brackets" href="#id15" id="id5">[5]</a> that any solution to better string interpolation would not use locals() or globals() in its implementation. (This does not forbid users from passing locals() or globals() in, it just doesn’t require it, nor does it allow using these functions under the hood.)</p> </section> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <p>In source code, f-strings are string literals that are prefixed by the letter ‘f’ or ‘F’. Everywhere this PEP uses ‘f’, ‘F’ may also be used. ‘f’ may be combined with ‘r’ or ‘R’, in either order, to produce raw f-string literals. ‘f’ may not be combined with ‘b’: this PEP does not propose to add binary f-strings. ‘f’ may not be combined with ‘u’.</p> <p>When tokenizing source files, f-strings use the same rules as normal strings, raw strings, binary strings, and triple quoted strings. That is, the string must end with the same character that it started with: if it starts with a single quote it must end with a single quote, etc. This implies that any code that currently scans Python code looking for strings should be trivially modifiable to recognize f-strings (parsing within an f-string is another matter, of course).</p> <p>Once tokenized, f-strings are parsed in to literal strings and expressions. Expressions appear within curly braces <code class="docutils literal notranslate"><span class="pre">'{'</span></code> and <code class="docutils literal notranslate"><span class="pre">'}'</span></code>. While scanning the string for expressions, any doubled braces <code class="docutils literal notranslate"><span class="pre">'{{'</span></code> or <code class="docutils literal notranslate"><span class="pre">'}}'</span></code> inside literal portions of an f-string are replaced by the corresponding single brace. Doubled literal opening braces do not signify the start of an expression. A single closing curly brace <code class="docutils literal notranslate"><span class="pre">'}'</span></code> in the literal portion of a string is an error: literal closing curly braces must be doubled <code class="docutils literal notranslate"><span class="pre">'}}'</span></code> in order to represent a single closing brace.</p> <p>The parts of the f-string outside of braces are literal strings. These literal portions are then decoded. For non-raw f-strings, this includes converting backslash escapes such as <code class="docutils literal notranslate"><span class="pre">'\n'</span></code>, <code class="docutils literal notranslate"><span class="pre">'\&quot;'</span></code>, <code class="docutils literal notranslate"><span class="pre">&quot;\'&quot;</span></code>, <code class="docutils literal notranslate"><span class="pre">'\xhh'</span></code>, <code class="docutils literal notranslate"><span class="pre">'\uxxxx'</span></code>, <code class="docutils literal notranslate"><span class="pre">'\Uxxxxxxxx'</span></code>, and named unicode characters <code class="docutils literal notranslate"><span class="pre">'\N{name}'</span></code> into their associated Unicode characters <a class="footnote-reference brackets" href="#id16" id="id6">[6]</a>.</p> <p>Backslashes may not appear anywhere within expressions. Comments, using the <code class="docutils literal notranslate"><span class="pre">'#'</span></code> character, are not allowed inside an expression.</p> <p>Following each expression, an optional type conversion may be specified. The allowed conversions are <code class="docutils literal notranslate"><span class="pre">'!s'</span></code>, <code class="docutils literal notranslate"><span class="pre">'!r'</span></code>, or <code class="docutils literal notranslate"><span class="pre">'!a'</span></code>. These are treated the same as in <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>: <code class="docutils literal notranslate"><span class="pre">'!s'</span></code> calls <code class="docutils literal notranslate"><span class="pre">str()</span></code> on the expression, <code class="docutils literal notranslate"><span class="pre">'!r'</span></code> calls <code class="docutils literal notranslate"><span class="pre">repr()</span></code> on the expression, and <code class="docutils literal notranslate"><span class="pre">'!a'</span></code> calls <code class="docutils literal notranslate"><span class="pre">ascii()</span></code> on the expression. These conversions are applied before the call to <code class="docutils literal notranslate"><span class="pre">format()</span></code>. The only reason to use <code class="docutils literal notranslate"><span class="pre">'!s'</span></code> is if you want to specify a format specifier that applies to <code class="docutils literal notranslate"><span class="pre">str</span></code>, not to the type of the expression.</p> <p>F-strings use the same format specifier mini-language as <code class="docutils literal notranslate"><span class="pre">str.format</span></code>. Similar to <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>, optional format specifiers maybe be included inside the f-string, separated from the expression (or the type conversion, if specified) by a colon. If a format specifier is not provided, an empty string is used.</p> <p>So, an f-string looks like:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">f</span> <span class="s1">&#39; &lt;text&gt; { &lt;expression&gt; &lt;optional !s, !r, or !a&gt; &lt;optional : format specifier&gt; } &lt;text&gt; ... &#39;</span> </pre></div> </div> <p>The expression is then formatted using the <code class="docutils literal notranslate"><span class="pre">__format__</span></code> protocol, using the format specifier as an argument. The resulting value is used when building the value of the f-string.</p> <p>Note that <code class="docutils literal notranslate"><span class="pre">__format__()</span></code> is not called directly on each value. The actual code uses the equivalent of <code class="docutils literal notranslate"><span class="pre">type(value).__format__(value,</span> <span class="pre">format_spec)</span></code>, or <code class="docutils literal notranslate"><span class="pre">format(value,</span> <span class="pre">format_spec)</span></code>. See the documentation of the builtin <code class="docutils literal notranslate"><span class="pre">format()</span></code> function for more details.</p> <p>Expressions cannot contain <code class="docutils literal notranslate"><span class="pre">':'</span></code> or <code class="docutils literal notranslate"><span class="pre">'!'</span></code> outside of strings or parentheses, brackets, or braces. The exception is that the <code class="docutils literal notranslate"><span class="pre">'!='</span></code> operator is allowed as a special case.</p> <section id="escape-sequences"> <h3><a class="toc-backref" href="#escape-sequences" role="doc-backlink">Escape sequences</a></h3> <p>Backslashes may not appear inside the expression portions of f-strings, so you cannot use them, for example, to escape quotes inside f-strings:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; f&#39;{\&#39;quoted string\&#39;}&#39; File &quot;&lt;stdin&gt;&quot;, line 1 SyntaxError: f-string expression part cannot include a backslash </pre></div> </div> <p>You can use a different type of quote inside the expression:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="s2">&quot;quoted string&quot;</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;quoted string&#39;</span> </pre></div> </div> <p>Backslash escapes may appear inside the string portions of an f-string.</p> <p>Note that the correct way to have a literal brace appear in the resulting string value is to double the brace:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="se">{{</span><span class="s1"> </span><span class="si">{</span><span class="mi">4</span><span class="o">*</span><span class="mi">10</span><span class="si">}</span><span class="s1"> </span><span class="se">}}</span><span class="s1">&#39;</span> <span class="go">&#39;{ 40 }&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="se">{{</span><span class="si">{</span><span class="mi">4</span><span class="o">*</span><span class="mi">10</span><span class="si">}</span><span class="se">}}</span><span class="s1">&#39;</span> <span class="go">&#39;{40}&#39;</span> </pre></div> </div> <p>Like all raw strings in Python, no escape processing is done for raw f-strings:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">fr</span><span class="s1">&#39;x=</span><span class="si">{</span><span class="mi">4</span><span class="o">*</span><span class="mi">10</span><span class="si">}</span><span class="s1">\n&#39;</span> <span class="go">&#39;x=40\\n&#39;</span> </pre></div> </div> <p>Due to Python’s string tokenizing rules, the f-string <code class="docutils literal notranslate"><span class="pre">f'abc</span> <span class="pre">{a['x']}</span> <span class="pre">def'</span></code> is invalid. The tokenizer parses this as 3 tokens: <code class="docutils literal notranslate"><span class="pre">f'abc</span> <span class="pre">{a['</span></code>, <code class="docutils literal notranslate"><span class="pre">x</span></code>, and <code class="docutils literal notranslate"><span class="pre">']}</span> <span class="pre">def'</span></code>. Just like regular strings, this cannot be fixed by using raw strings. There are a number of correct ways to write this f-string: with a different quote character:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="sa">f</span><span class="s2">&quot;abc </span><span class="si">{</span><span class="n">a</span><span class="p">[</span><span class="s1">&#39;x&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2"> def&quot;</span> </pre></div> </div> <p>Or with triple quotes:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="sa">f</span><span class="s1">&#39;&#39;&#39;abc </span><span class="si">{</span><span class="n">a</span><span class="p">[</span><span class="s1">&#39;x&#39;</span><span class="p">]</span><span class="si">}</span><span class="s1"> def&#39;&#39;&#39;</span> </pre></div> </div> </section> <section id="code-equivalence"> <h3><a class="toc-backref" href="#code-equivalence" role="doc-backlink">Code equivalence</a></h3> <p>The exact code used to implement f-strings is not specified. However, it is guaranteed that any embedded value that is converted to a string will use that value’s <code class="docutils literal notranslate"><span class="pre">__format__</span></code> method. This is the same mechanism that <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> uses to convert values to strings.</p> <p>For example, this code:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="sa">f</span><span class="s1">&#39;abc</span><span class="si">{</span><span class="n">expr1</span><span class="si">:</span><span class="s1">spec1</span><span class="si">}{</span><span class="n">expr2</span><span class="si">!r:</span><span class="s1">spec2</span><span class="si">}</span><span class="s1">def</span><span class="si">{</span><span class="n">expr3</span><span class="si">}</span><span class="s1">ghi&#39;</span> </pre></div> </div> <p>Might be evaluated as:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s1">&#39;abc&#39;</span> <span class="o">+</span> <span class="nb">format</span><span class="p">(</span><span class="n">expr1</span><span class="p">,</span> <span class="n">spec1</span><span class="p">)</span> <span class="o">+</span> <span class="nb">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">expr2</span><span class="p">),</span> <span class="n">spec2</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;def&#39;</span> <span class="o">+</span> <span class="nb">format</span><span class="p">(</span><span class="n">expr3</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;ghi&#39;</span> </pre></div> </div> </section> <section id="expression-evaluation"> <h3><a class="toc-backref" href="#expression-evaluation" role="doc-backlink">Expression evaluation</a></h3> <p>The expressions that are extracted from the string are evaluated in the context where the f-string appeared. This means the expression has full access to local and global variables. Any valid Python expression can be used, including function and method calls.</p> <p>Because the f-strings are evaluated where the string appears in the source code, there is no additional expressiveness available with f-strings. There are also no additional security concerns: you could have also just written the same expression, not inside of an f-string:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">():</span> <span class="gp">... </span> <span class="k">return</span> <span class="mi">20</span> <span class="gp">...</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;result=</span><span class="si">{</span><span class="n">foo</span><span class="p">()</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;result=20&#39;</span> </pre></div> </div> <p>Is equivalent to:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;result=&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">foo</span><span class="p">())</span> <span class="go">&#39;result=20&#39;</span> </pre></div> </div> <p>Expressions are parsed with the equivalent of <code class="docutils literal notranslate"><span class="pre">ast.parse('('</span> <span class="pre">+</span> <span class="pre">expression</span> <span class="pre">+</span> <span class="pre">')',</span> <span class="pre">'&lt;fstring&gt;',</span> <span class="pre">'eval')</span></code> <a class="footnote-reference brackets" href="#id17" id="id7">[7]</a>.</p> <p>Note that since the expression is enclosed by implicit parentheses before evaluation, expressions can contain newlines. For example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;&#39;&#39;</span><span class="si">{</span><span class="n">x</span> <span class="gp">... </span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s1">&#39;&#39;&#39;</span> <span class="go">&#39;1&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">:</span> <span class="s1">&#39;zero&#39;</span><span class="p">}</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;&#39;&#39;</span><span class="si">{</span><span class="n">d</span><span class="p">[</span><span class="mi">0</span> <span class="gp">... </span><span class="p">]</span><span class="si">}</span><span class="s1">&#39;&#39;&#39;</span> <span class="go">&#39;zero&#39;</span> </pre></div> </div> </section> <section id="format-specifiers"> <h3><a class="toc-backref" href="#format-specifiers" role="doc-backlink">Format specifiers</a></h3> <p>Format specifiers may also contain evaluated expressions. This allows code such as:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">width</span> <span class="o">=</span> <span class="mi">10</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">precision</span> <span class="o">=</span> <span class="mi">4</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">value</span> <span class="o">=</span> <span class="n">decimal</span><span class="o">.</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">&#39;12.34567&#39;</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;result: </span><span class="si">{</span><span class="n">value</span><span class="si">:{</span><span class="n">width</span><span class="si">}</span><span class="s1">.</span><span class="si">{</span><span class="n">precision</span><span class="si">}}</span><span class="s1">&#39;</span> <span class="go">&#39;result: 12.35&#39;</span> </pre></div> </div> <p>Once expressions in a format specifier are evaluated (if necessary), format specifiers are not interpreted by the f-string evaluator. Just as in <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>, they are merely passed in to the <code class="docutils literal notranslate"><span class="pre">__format__()</span></code> method of the object being formatted.</p> </section> <section id="concatenating-strings"> <h3><a class="toc-backref" href="#concatenating-strings" role="doc-backlink">Concatenating strings</a></h3> <p>Adjacent f-strings and regular strings are concatenated. Regular strings are concatenated at compile time, and f-strings are concatenated at run time. For example, the expression:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mi">10</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">y</span> <span class="o">=</span> <span class="s1">&#39;hi&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;a&#39;</span> <span class="s1">&#39;b&#39;</span> <span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s1">&#39;</span> <span class="s1">&#39;</span><span class="si">{c}</span><span class="s1">&#39;</span> <span class="sa">f</span><span class="s1">&#39;str&lt;</span><span class="si">{</span><span class="n">y</span><span class="si">:</span><span class="s1">^4</span><span class="si">}</span><span class="s1">&gt;&#39;</span> <span class="s1">&#39;d&#39;</span> <span class="s1">&#39;e&#39;</span> </pre></div> </div> <p>yields the value:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s1">&#39;ab10</span><span class="si">{c}</span><span class="s1">str&lt; hi &gt;de&#39;</span> </pre></div> </div> <p>While the exact method of this run time concatenation is unspecified, the above code might evaluate to:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s1">&#39;ab&#39;</span> <span class="o">+</span> <span class="nb">format</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;</span><span class="si">{c}</span><span class="s1">&#39;</span> <span class="o">+</span> <span class="s1">&#39;str&lt;&#39;</span> <span class="o">+</span> <span class="nb">format</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="s1">&#39;^4&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;&gt;de&#39;</span> </pre></div> </div> <p>Each f-string is entirely evaluated before being concatenated to adjacent f-strings. That means that this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">x</span><span class="s1">&#39; f&#39;</span><span class="si">}</span><span class="s1">&#39;</span> </pre></div> </div> <p>Is a syntax error, because the first f-string does not contain a closing brace.</p> </section> <section id="error-handling"> <h3><a class="toc-backref" href="#error-handling" role="doc-backlink">Error handling</a></h3> <p>Either compile time or run time errors can occur when processing f-strings. Compile time errors are limited to those errors that can be detected when scanning an f-string. These errors all raise <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>.</p> <p>Unmatched braces:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;x=</span><span class="si">{</span><span class="n">x</span><span class="s1">&#39;</span> File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span> <span class="gr">SyntaxError</span>: <span class="n">f-string: expecting &#39;}&#39;</span> </pre></div> </div> <p>Invalid expressions:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; f&#39;x={!x}&#39; File &quot;&lt;stdin&gt;&quot;, line 1 SyntaxError: f-string: empty expression not allowed </pre></div> </div> <p>Run time errors occur when evaluating the expressions inside an f-string. Note that an f-string can be evaluated multiple times, and work sometimes and raise an error at other times:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">:</span><span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span><span class="mi">20</span><span class="p">}</span> <span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span> <span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s1">:</span><span class="si">{</span><span class="n">d</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span> <span class="gp">...</span> <span class="go">0:10</span> <span class="go">1:20</span> <span class="gt">Traceback (most recent call last):</span> File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">2</span>, in <span class="n">&lt;module&gt;</span> <span class="gr">KeyError</span>: <span class="n">2</span> </pre></div> </div> <p>or:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="s1">&#39;fifty&#39;</span><span class="p">):</span> <span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;x = </span><span class="si">{</span><span class="n">x</span><span class="si">:</span><span class="s1">+3</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span> <span class="gp">...</span> <span class="go">&#39;x = +32&#39;</span> <span class="go">&#39;x = +100&#39;</span> <span class="gt">Traceback (most recent call last):</span> File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">2</span>, in <span class="n">&lt;module&gt;</span> <span class="gr">ValueError</span>: <span class="n">Sign not allowed in string format specifier</span> </pre></div> </div> </section> <section id="leading-and-trailing-whitespace-in-expressions-is-ignored"> <h3><a class="toc-backref" href="#leading-and-trailing-whitespace-in-expressions-is-ignored" role="doc-backlink">Leading and trailing whitespace in expressions is ignored</a></h3> <p>For ease of readability, leading and trailing whitespace in expressions is ignored. This is a by-product of enclosing the expression in parentheses before evaluation.</p> </section> <section id="evaluation-order-of-expressions"> <h3><a class="toc-backref" href="#evaluation-order-of-expressions" role="doc-backlink">Evaluation order of expressions</a></h3> <p>The expressions in an f-string are evaluated in left-to-right order. This is detectable only if the expressions have side effects:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span><span class="w"> </span><span class="nf">fn</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">incr</span><span class="p">):</span> <span class="gp">... </span> <span class="n">result</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="gp">... </span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="n">incr</span> <span class="gp">... </span> <span class="k">return</span> <span class="n">result</span> <span class="gp">...</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">lst</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">fn</span><span class="p">(</span><span class="n">lst</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span><span class="si">}</span><span class="s1"> </span><span class="si">{</span><span class="n">fn</span><span class="p">(</span><span class="n">lst</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;0 2&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">fn</span><span class="p">(</span><span class="n">lst</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span><span class="si">}</span><span class="s1"> </span><span class="si">{</span><span class="n">fn</span><span class="p">(</span><span class="n">lst</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;5 7&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">lst</span> <span class="go">[10]</span> </pre></div> </div> </section> </section> <section id="discussion"> <h2><a class="toc-backref" href="#discussion" role="doc-backlink">Discussion</a></h2> <section id="python-ideas-discussion"> <h3><a class="toc-backref" href="#python-ideas-discussion" role="doc-backlink">python-ideas discussion</a></h3> <p>Most of the discussions on python-ideas <a class="footnote-reference brackets" href="#id18" id="id8">[8]</a> focused on three issues:</p> <ul class="simple"> <li>How to denote f-strings,</li> <li>How to specify the location of expressions in f-strings, and</li> <li>Whether to allow full Python expressions.</li> </ul> <section id="how-to-denote-f-strings"> <h4><a class="toc-backref" href="#how-to-denote-f-strings" role="doc-backlink">How to denote f-strings</a></h4> <p>Because the compiler must be involved in evaluating the expressions contained in the interpolated strings, there must be some way to denote to the compiler which strings should be evaluated. This PEP chose a leading <code class="docutils literal notranslate"><span class="pre">'f'</span></code> character preceding the string literal. This is similar to how <code class="docutils literal notranslate"><span class="pre">'b'</span></code> and <code class="docutils literal notranslate"><span class="pre">'r'</span></code> prefixes change the meaning of the string itself, at compile time. Other prefixes were suggested, such as <code class="docutils literal notranslate"><span class="pre">'i'</span></code>. No option seemed better than the other, so <code class="docutils literal notranslate"><span class="pre">'f'</span></code> was chosen.</p> <p>Another option was to support special functions, known to the compiler, such as <code class="docutils literal notranslate"><span class="pre">Format()</span></code>. This seems like too much magic for Python: not only is there a chance for collision with existing identifiers, the PEP author feels that it’s better to signify the magic with a string prefix character.</p> </section> <section id="how-to-specify-the-location-of-expressions-in-f-strings"> <h4><a class="toc-backref" href="#how-to-specify-the-location-of-expressions-in-f-strings" role="doc-backlink">How to specify the location of expressions in f-strings</a></h4> <p>This PEP supports the same syntax as <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> for distinguishing replacement text inside strings: expressions are contained inside braces. There were other options suggested, such as <code class="docutils literal notranslate"><span class="pre">string.Template</span></code>’s <code class="docutils literal notranslate"><span class="pre">$identifier</span></code> or <code class="docutils literal notranslate"><span class="pre">${expression}</span></code>.</p> <p>While <code class="docutils literal notranslate"><span class="pre">$identifier</span></code> is no doubt more familiar to shell scripters and users of some other languages, in Python <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> is heavily used. A quick search of Python’s standard library shows only a handful of uses of <code class="docutils literal notranslate"><span class="pre">string.Template</span></code>, but hundreds of uses of <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>.</p> <p>Another proposed alternative was to have the substituted text between <code class="docutils literal notranslate"><span class="pre">\{</span></code> and <code class="docutils literal notranslate"><span class="pre">}</span></code> or between <code class="docutils literal notranslate"><span class="pre">\{</span></code> and <code class="docutils literal notranslate"><span class="pre">\}</span></code>. While this syntax would probably be desirable if all string literals were to support interpolation, this PEP only supports strings that are already marked with the leading <code class="docutils literal notranslate"><span class="pre">'f'</span></code>. As such, the PEP is using unadorned braces to denoted substituted text, in order to leverage end user familiarity with <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>.</p> </section> <section id="supporting-full-python-expressions"> <h4><a class="toc-backref" href="#supporting-full-python-expressions" role="doc-backlink">Supporting full Python expressions</a></h4> <p>Many people on the python-ideas discussion wanted support for either only single identifiers, or a limited subset of Python expressions (such as the subset supported by <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>). This PEP supports full Python expressions inside the braces. Without full expressions, some desirable usage would be cumbersome. For example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;Column=</span><span class="si">{</span><span class="n">col_idx</span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s1">&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;number of items: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">items</span><span class="p">)</span><span class="si">}</span><span class="s1">&#39;</span> </pre></div> </div> <p>would become:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">col_number</span> <span class="o">=</span> <span class="n">col_idx</span><span class="o">+</span><span class="mi">1</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;Column=</span><span class="si">{</span><span class="n">col_number</span><span class="si">}</span><span class="s1">&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">n_items</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">items</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;number of items: </span><span class="si">{</span><span class="n">n_items</span><span class="si">}</span><span class="s1">&#39;</span> </pre></div> </div> <p>While it’s true that very ugly expressions could be included in the f-strings, this PEP takes the position that such uses should be addressed in a linter or code review:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;mapping is </span><span class="si">{</span><span class="w"> </span><span class="p">{</span><span class="n">a</span><span class="p">:</span><span class="n">b</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">((</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">))}</span><span class="w"> </span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;mapping is {1: 2, 3: 4}&#39;</span> </pre></div> </div> </section> </section> <section id="similar-support-in-other-languages"> <h3><a class="toc-backref" href="#similar-support-in-other-languages" role="doc-backlink">Similar support in other languages</a></h3> <p>Wikipedia has a good discussion of string interpolation in other programming languages <a class="footnote-reference brackets" href="#id19" id="id9">[9]</a>. This feature is implemented in many languages, with a variety of syntaxes and restrictions.</p> </section> <section id="differences-between-f-string-and-str-format-expressions"> <h3><a class="toc-backref" href="#differences-between-f-string-and-str-format-expressions" role="doc-backlink">Differences between f-string and str.format expressions</a></h3> <p>There is one small difference between the limited expressions allowed in <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> and the full expressions allowed inside f-strings. The difference is in how index lookups are performed. In <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>, index values that do not look like numbers are converted to strings:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;a&#39;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">&#39;b&#39;</span><span class="p">:</span> <span class="mi">20</span><span class="p">}</span> <span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;a=</span><span class="si">{d[a]}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">d</span><span class="o">=</span><span class="n">d</span><span class="p">)</span> <span class="go">&#39;a=10&#39;</span> </pre></div> </div> <p>Notice that the index value is converted to the string <code class="docutils literal notranslate"><span class="pre">'a'</span></code> when it is looked up in the dict.</p> <p>However, in f-strings, you would need to use a literal for the value of <code class="docutils literal notranslate"><span class="pre">'a'</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;a=</span><span class="si">{</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;a&quot;</span><span class="p">]</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;a=10&#39;</span> </pre></div> </div> <p>This difference is required because otherwise you would not be able to use variables as index values:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="s1">&#39;b&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;a=</span><span class="si">{</span><span class="n">d</span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;a=20&#39;</span> </pre></div> </div> <p>See <a class="footnote-reference brackets" href="#id20" id="id10">[10]</a> for a further discussion. It was this observation that led to full Python expressions being supported in f-strings.</p> <p>Furthermore, the limited expressions that <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> understands need not be valid Python expressions. For example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;</span><span class="si">{i[&quot;;]}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;&quot;;&#39;</span><span class="p">:</span><span class="mi">4</span><span class="p">})</span> <span class="go">&#39;4&#39;</span> </pre></div> </div> <p>For this reason, the str.format() “expression parser” is not suitable for use when implementing f-strings.</p> </section> <section id="triple-quoted-f-strings"> <h3><a class="toc-backref" href="#triple-quoted-f-strings" role="doc-backlink">Triple-quoted f-strings</a></h3> <p>Triple quoted f-strings are allowed. These strings are parsed just as normal triple-quoted strings are. After parsing and decoding, the normal f-string logic is applied, and <code class="docutils literal notranslate"><span class="pre">__format__()</span></code> is called on each value.</p> </section> <section id="raw-f-strings"> <h3><a class="toc-backref" href="#raw-f-strings" role="doc-backlink">Raw f-strings</a></h3> <p>Raw and f-strings may be combined. For example, they could be used to build up regular expressions:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">header</span> <span class="o">=</span> <span class="s1">&#39;Subject&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">fr</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">header</span><span class="si">}</span><span class="s1">:\s+&#39;</span> <span class="go">&#39;Subject:\\s+&#39;</span> </pre></div> </div> <p>In addition, raw f-strings may be combined with triple-quoted strings.</p> </section> <section id="no-binary-f-strings"> <h3><a class="toc-backref" href="#no-binary-f-strings" role="doc-backlink">No binary f-strings</a></h3> <p>For the same reason that we don’t support <code class="docutils literal notranslate"><span class="pre">bytes.format()</span></code>, you may not combine <code class="docutils literal notranslate"><span class="pre">'f'</span></code> with <code class="docutils literal notranslate"><span class="pre">'b'</span></code> string literals. The primary problem is that an object’s <code class="docutils literal notranslate"><span class="pre">__format__()</span></code> method may return Unicode data that is not compatible with a bytes string.</p> <p>Binary f-strings would first require a solution for <code class="docutils literal notranslate"><span class="pre">bytes.format()</span></code>. This idea has been proposed in the past, most recently in <a class="pep reference internal" href="../pep-0461/#proposed-variations" title="PEP 461 – Adding % formatting to bytes and bytearray § Proposed variations">PEP 461</a>. The discussions of such a feature usually suggest either</p> <ul class="simple"> <li>adding a method such as <code class="docutils literal notranslate"><span class="pre">__bformat__()</span></code> so an object can control how it is converted to bytes, or</li> <li>having <code class="docutils literal notranslate"><span class="pre">bytes.format()</span></code> not be as general purpose or extensible as <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>.</li> </ul> <p>Both of these remain as options in the future, if such functionality is desired.</p> </section> <section id="s-r-and-a-are-redundant"> <h3><a class="toc-backref" href="#s-r-and-a-are-redundant" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">!s</span></code>, <code class="docutils literal notranslate"><span class="pre">!r</span></code>, and <code class="docutils literal notranslate"><span class="pre">!a</span></code> are redundant</a></h3> <p>The <code class="docutils literal notranslate"><span class="pre">!s</span></code>, <code class="docutils literal notranslate"><span class="pre">!r</span></code>, and <code class="docutils literal notranslate"><span class="pre">!a</span></code> conversions are not strictly required. Because arbitrary expressions are allowed inside the f-strings, this code:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="s1">&#39;some string&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">a</span><span class="si">!r}</span><span class="s1">&#39;</span> <span class="go">&quot;&#39;some string&#39;&quot;</span> </pre></div> </div> <p>Is identical to:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="nb">repr</span><span class="p">(</span><span class="n">a</span><span class="p">)</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&quot;&#39;some string&#39;&quot;</span> </pre></div> </div> <p>Similarly, <code class="docutils literal notranslate"><span class="pre">!s</span></code> can be replaced by calls to <code class="docutils literal notranslate"><span class="pre">str()</span></code> and <code class="docutils literal notranslate"><span class="pre">!a</span></code> by calls to <code class="docutils literal notranslate"><span class="pre">ascii()</span></code>.</p> <p>However, <code class="docutils literal notranslate"><span class="pre">!s</span></code>, <code class="docutils literal notranslate"><span class="pre">!r</span></code>, and <code class="docutils literal notranslate"><span class="pre">!a</span></code> are supported by this PEP in order to minimize the differences with <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>. <code class="docutils literal notranslate"><span class="pre">!s</span></code>, <code class="docutils literal notranslate"><span class="pre">!r</span></code>, and <code class="docutils literal notranslate"><span class="pre">!a</span></code> are required in <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> because it does not allow the execution of arbitrary expressions.</p> </section> <section id="lambdas-inside-expressions"> <h3><a class="toc-backref" href="#lambdas-inside-expressions" role="doc-backlink">Lambdas inside expressions</a></h3> <p>Because lambdas use the <code class="docutils literal notranslate"><span class="pre">':'</span></code> character, they cannot appear outside of parentheses in an expression. The colon is interpreted as the start of the format specifier, which means the start of the lambda expression is seen and is syntactically invalid. As there’s no practical use for a plain lambda in an f-string expression, this is not seen as much of a limitation.</p> <p>If you feel you must use lambdas, they may be used inside of parentheses:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="p">(</span><span class="k">lambda</span><span class="w"> </span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="n">x</span><span class="o">*</span><span class="mi">2</span><span class="p">)(</span><span class="mi">3</span><span class="p">)</span><span class="si">}</span><span class="s1">&#39;</span> <span class="go">&#39;6&#39;</span> </pre></div> </div> </section> <section id="can-t-combine-with-u"> <h3><a class="toc-backref" href="#can-t-combine-with-u" role="doc-backlink">Can’t combine with ‘u’</a></h3> <p>The ‘u’ prefix was added to Python 3.3 in <a class="pep reference internal" href="../pep-0414/" title="PEP 414 – Explicit Unicode Literal for Python 3.3">PEP 414</a> as a means to ease source compatibility with Python 2.7. Because Python 2.7 will never support f-strings, there is nothing to be gained by being able to combine the ‘f’ prefix with ‘u’.</p> </section> </section> <section id="examples-from-python-s-source-code"> <h2><a class="toc-backref" href="#examples-from-python-s-source-code" role="doc-backlink">Examples from Python’s source code</a></h2> <p>Here are some examples from Python source code that currently use <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>, and how they would look with f-strings. This PEP does not recommend wholesale converting to f-strings, these are just examples of real-world usages of <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> and how they’d look if written from scratch using f-strings.</p> <p><code class="docutils literal notranslate"><span class="pre">Lib/asyncio/locks.py</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">extra</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="si">{}</span><span class="s1">,waiters:</span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">extra</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_waiters</span><span class="p">))</span> <span class="n">extra</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">extra</span><span class="si">}</span><span class="s1">,waiters:</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_waiters</span><span class="p">)</span><span class="si">}</span><span class="s1">&#39;</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">Lib/configparser.py</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot; [line </span><span class="si">{0:2d}</span><span class="s2">]&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">lineno</span><span class="p">))</span> <span class="n">message</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot; [line </span><span class="si">{</span><span class="n">lineno</span><span class="si">:</span><span class="s2">2d</span><span class="si">}</span><span class="s2">]&quot;</span><span class="p">)</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">Tools/clinic/clinic.py</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">methoddef_name</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2">_METHODDEF&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">c_basename</span><span class="o">.</span><span class="n">upper</span><span class="p">())</span> <span class="n">methoddef_name</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">c_basename</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s2">_METHODDEF&quot;</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">python-config.py</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Usage: </span><span class="si">{0}</span><span class="s2"> [</span><span class="si">{1}</span><span class="s2">]&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="s1">&#39;|&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39;--&#39;</span><span class="o">+</span><span class="n">opt</span> <span class="k">for</span> <span class="n">opt</span> <span class="ow">in</span> <span class="n">valid_opts</span><span class="p">)),</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Usage: </span><span class="si">{</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2"> [</span><span class="si">{</span><span class="s1">&#39;|&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39;--&#39;</span><span class="o">+</span><span class="n">opt</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">opt</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">valid_opts</span><span class="p">)</span><span class="si">}</span><span class="s2">]&quot;</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span> </pre></div> </div> </section> <section id="references"> <h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2> <aside class="footnote-list brackets"> <aside class="footnote brackets" id="id11" role="doc-footnote"> <dt class="label" id="id11">[<a href="#id1">1</a>]</dt> <dd>%-formatting (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting">https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting</a>)</aside> <aside class="footnote brackets" id="id12" role="doc-footnote"> <dt class="label" id="id12">[<a href="#id2">2</a>]</dt> <dd>str.format (<a class="reference external" href="https://docs.python.org/3/library/string.html#formatstrings">https://docs.python.org/3/library/string.html#formatstrings</a>)</aside> <aside class="footnote brackets" id="id13" role="doc-footnote"> <dt class="label" id="id13">[<a href="#id3">3</a>]</dt> <dd>string.Template documentation (<a class="reference external" href="https://docs.python.org/3/library/string.html#template-strings">https://docs.python.org/3/library/string.html#template-strings</a>)</aside> <aside class="footnote brackets" id="id14" role="doc-footnote"> <dt class="label" id="id14">[<a href="#id4">4</a>]</dt> <dd>Formatting using locals() and globals() (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034671.html">https://mail.python.org/pipermail/python-ideas/2015-July/034671.html</a>)</aside> <aside class="footnote brackets" id="id15" role="doc-footnote"> <dt class="label" id="id15">[<a href="#id5">5</a>]</dt> <dd>Avoid locals() and globals() (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034701.html">https://mail.python.org/pipermail/python-ideas/2015-July/034701.html</a>)</aside> <aside class="footnote brackets" id="id16" role="doc-footnote"> <dt class="label" id="id16">[<a href="#id6">6</a>]</dt> <dd>String literal description (<a class="reference external" href="https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals">https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals</a>)</aside> <aside class="footnote brackets" id="id17" role="doc-footnote"> <dt class="label" id="id17">[<a href="#id7">7</a>]</dt> <dd>ast.parse() documentation (<a class="reference external" href="https://docs.python.org/3/library/ast.html#ast.parse">https://docs.python.org/3/library/ast.html#ast.parse</a>)</aside> <aside class="footnote brackets" id="id18" role="doc-footnote"> <dt class="label" id="id18">[<a href="#id8">8</a>]</dt> <dd>Start of python-ideas discussion (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034657.html">https://mail.python.org/pipermail/python-ideas/2015-July/034657.html</a>)</aside> <aside class="footnote brackets" id="id19" role="doc-footnote"> <dt class="label" id="id19">[<a href="#id9">9</a>]</dt> <dd>Wikipedia article on string interpolation (<a class="reference external" href="https://en.wikipedia.org/wiki/String_interpolation">https://en.wikipedia.org/wiki/String_interpolation</a>)</aside> <aside class="footnote brackets" id="id20" role="doc-footnote"> <dt class="label" id="id20">[<a href="#id10">10</a>]</dt> <dd>Differences in str.format() and f-string expressions (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034726.html">https://mail.python.org/pipermail/python-ideas/2015-July/034726.html</a>)</aside> </aside> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0498.rst">https://github.com/python/peps/blob/main/peps/pep-0498.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0498.rst">2025-02-01 08:59:27 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#no-use-of-globals-or-locals">No use of globals() or locals()</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#escape-sequences">Escape sequences</a></li> <li><a class="reference internal" href="#code-equivalence">Code equivalence</a></li> <li><a class="reference internal" href="#expression-evaluation">Expression evaluation</a></li> <li><a class="reference internal" href="#format-specifiers">Format specifiers</a></li> <li><a class="reference internal" href="#concatenating-strings">Concatenating strings</a></li> <li><a class="reference internal" href="#error-handling">Error handling</a></li> <li><a class="reference internal" href="#leading-and-trailing-whitespace-in-expressions-is-ignored">Leading and trailing whitespace in expressions is ignored</a></li> <li><a class="reference internal" href="#evaluation-order-of-expressions">Evaluation order of expressions</a></li> </ul> </li> <li><a class="reference internal" href="#discussion">Discussion</a><ul> <li><a class="reference internal" href="#python-ideas-discussion">python-ideas discussion</a><ul> <li><a class="reference internal" href="#how-to-denote-f-strings">How to denote f-strings</a></li> <li><a class="reference internal" href="#how-to-specify-the-location-of-expressions-in-f-strings">How to specify the location of expressions in f-strings</a></li> <li><a class="reference internal" href="#supporting-full-python-expressions">Supporting full Python expressions</a></li> </ul> </li> <li><a class="reference internal" href="#similar-support-in-other-languages">Similar support in other languages</a></li> <li><a class="reference internal" href="#differences-between-f-string-and-str-format-expressions">Differences between f-string and str.format expressions</a></li> <li><a class="reference internal" href="#triple-quoted-f-strings">Triple-quoted f-strings</a></li> <li><a class="reference internal" href="#raw-f-strings">Raw f-strings</a></li> <li><a class="reference internal" href="#no-binary-f-strings">No binary f-strings</a></li> <li><a class="reference internal" href="#s-r-and-a-are-redundant"><code class="docutils literal notranslate"><span class="pre">!s</span></code>, <code class="docutils literal notranslate"><span class="pre">!r</span></code>, and <code class="docutils literal notranslate"><span class="pre">!a</span></code> are redundant</a></li> <li><a class="reference internal" href="#lambdas-inside-expressions">Lambdas inside expressions</a></li> <li><a class="reference internal" href="#can-t-combine-with-u">Can’t combine with ‘u’</a></li> </ul> </li> <li><a class="reference internal" href="#examples-from-python-s-source-code">Examples from Python’s source code</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0498.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10