CINXE.COM
PEP 502 – String Interpolation - Extended Discussion | 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 502 – String Interpolation - Extended Discussion | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0502/"> <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 502 – String Interpolation - Extended Discussion | peps.python.org'> <meta property="og:description" content="PEP 498: Literal String Interpolation, which proposed “formatted strings” was accepted September 9th, 2015. Additional background and rationale given during its design phase is detailed below."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0502/"> <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="PEP 498: Literal String Interpolation, which proposed “formatted strings” was accepted September 9th, 2015. Additional background and rationale given during its design phase is detailed below."> <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> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 502</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 502 – String Interpolation - Extended Discussion</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Mike G. Miller</dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">10-Aug-2015</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">3.6</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="#pep-status">PEP Status</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#goals">Goals</a></li> <li><a class="reference internal" href="#limitations">Limitations</a></li> <li><a class="reference internal" href="#background">Background</a><ul> <li><a class="reference internal" href="#printf-style-formatting-via-operator">Printf-style formatting, via operator</a></li> <li><a class="reference internal" href="#string-template-class">string.Template Class</a></li> <li><a class="reference internal" href="#pep-215-string-interpolation">PEP 215 - String Interpolation</a></li> <li><a class="reference internal" href="#str-format-method">str.format() Method</a></li> <li><a class="reference internal" href="#pep-498-literal-string-formatting">PEP 498 – Literal String Formatting</a></li> <li><a class="reference internal" href="#pep-501-translation-ready-string-interpolation">PEP 501 – Translation ready string interpolation</a></li> </ul> </li> <li><a class="reference internal" href="#implementations-in-other-languages">Implementations in Other Languages</a><ul> <li><a class="reference internal" href="#bash">Bash</a></li> <li><a class="reference internal" href="#perl">Perl</a></li> <li><a class="reference internal" href="#ruby">Ruby</a></li> <li><a class="reference internal" href="#others">Others</a></li> <li><a class="reference internal" href="#scala">Scala</a></li> <li><a class="reference internal" href="#es6-javascript">ES6 (Javascript)</a></li> <li><a class="reference internal" href="#c-version-6">C#, Version 6</a></li> <li><a class="reference internal" href="#apple-s-swift">Apple’s Swift</a></li> <li><a class="reference internal" href="#additional-examples">Additional examples</a></li> </ul> </li> <li><a class="reference internal" href="#new-syntax">New Syntax</a></li> <li><a class="reference internal" href="#new-string-prefix">New String Prefix</a></li> </ul> </li> <li><a class="reference internal" href="#additional-topics">Additional Topics</a><ul> <li><a class="reference internal" href="#safety">Safety</a><ul> <li><a class="reference internal" href="#mitigation-via-tools">Mitigation via Tools</a></li> </ul> </li> <li><a class="reference internal" href="#style-guide-precautions">Style Guide/Precautions</a></li> <li><a class="reference internal" href="#reference-implementation-s">Reference Implementation(s)</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#postponed-ideas">Postponed Ideas</a><ul> <li><a class="reference internal" href="#internationalization">Internationalization</a></li> </ul> </li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#restricting-syntax-to-str-format-only">Restricting Syntax to <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> Only</a></li> <li><a class="reference internal" href="#additional-custom-string-prefixes">Additional/Custom String-Prefixes</a></li> <li><a class="reference internal" href="#automated-escaping-of-input-variables">Automated Escaping of Input Variables</a></li> <li><a class="reference internal" href="#environment-access-and-command-substitution">Environment Access and Command Substitution</a></li> </ul> </li> </ul> </li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</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><a class="pep reference internal" href="../pep-0498/" title="PEP 498 – Literal String Interpolation">PEP 498</a>: <em>Literal String Interpolation</em>, which proposed “formatted strings” was accepted September 9th, 2015. Additional background and rationale given during its design phase is detailed below.</p> <p>To recap that PEP, a string prefix was introduced that marks the string as a template to be rendered. These formatted strings may contain one or more expressions built on <a class="reference external" href="https://docs.python.org/3/library/string.html#format-string-syntax">the existing syntax</a> of <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>. <a class="footnote-reference brackets" href="#id25" id="id1">[10]</a> <a class="footnote-reference brackets" href="#id26" id="id2">[11]</a> The formatted string expands at compile-time into a conventional string format operation, with the given expressions from its text extracted and passed instead as positional arguments.</p> <p>At runtime, the resulting expressions are evaluated to render a string to given specifications:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">location</span> <span class="o">=</span> <span class="s1">'World'</span> <span class="gp">>>> </span><span class="sa">f</span><span class="s1">'Hello, </span><span class="si">{</span><span class="n">location</span><span class="si">}</span><span class="s1"> !'</span> <span class="c1"># new prefix: f''</span> <span class="go">'Hello, World !' # interpolated result</span> </pre></div> </div> <p>Format-strings may be thought of as merely syntactic sugar to simplify traditional calls to <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>.</p> </section> <section id="pep-status"> <h2><a class="toc-backref" href="#pep-status" role="doc-backlink">PEP Status</a></h2> <p>This PEP was rejected based on its using an opinion-based tone rather than a factual one. This PEP was also deemed not critical as <a class="pep reference internal" href="../pep-0498/" title="PEP 498 – Literal String Interpolation">PEP 498</a> was already written and should be the place to house design decision details.</p> </section> <section id="motivation"> <h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2> <p>Though string formatting and manipulation features are plentiful in Python, one area where it falls short is the lack of a convenient string interpolation syntax. In comparison to other dynamic scripting languages with similar use cases, the amount of code necessary to build similar strings is substantially higher, while at times offering lower readability due to verbosity, dense syntax, or identifier duplication.</p> <p>These difficulties are described at moderate length in the original <a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034659.html">post to python-ideas</a> that started the snowball (that became <a class="pep reference internal" href="../pep-0498/" title="PEP 498 – Literal String Interpolation">PEP 498</a>) rolling. <a class="footnote-reference brackets" href="#id16" id="id3">[1]</a></p> <p>Furthermore, replacement of the print statement with the more consistent print function of Python 3 (<a class="pep reference internal" href="../pep-3105/" title="PEP 3105 – Make print a function">PEP 3105</a>) has added one additional minor burden, an additional set of parentheses to type and read. Combined with the verbosity of current string formatting solutions, this puts an otherwise simple language at an unfortunate disadvantage to its peers:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">echo</span> <span class="s2">"Hello, user: $user, id: $id, on host: $hostname"</span> <span class="c1"># bash</span> <span class="n">say</span> <span class="s2">"Hello, user: $user, id: $id, on host: $hostname"</span><span class="p">;</span> <span class="c1"># perl</span> <span class="n">puts</span> <span class="s2">"Hello, user: #</span><span class="si">{user}</span><span class="s2">, id: #</span><span class="si">{id}</span><span class="s2">, on host: #</span><span class="si">{hostname}</span><span class="se">\n</span><span class="s2">"</span> <span class="c1"># ruby</span> <span class="c1"># 80 ch -->|</span> <span class="c1"># Python 3, str.format with named parameters</span> <span class="nb">print</span><span class="p">(</span><span class="s1">'Hello, user: </span><span class="si">{user}</span><span class="s1">, id: </span><span class="si">{id}</span><span class="s1">, on host: </span><span class="si">{hostname}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="o">**</span><span class="nb">locals</span><span class="p">()))</span> <span class="c1"># Python 3, worst case</span> <span class="nb">print</span><span class="p">(</span><span class="s1">'Hello, user: </span><span class="si">{user}</span><span class="s1">, id: </span><span class="si">{id}</span><span class="s1">, on host: </span><span class="si">{hostname}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">user</span><span class="o">=</span><span class="n">user</span><span class="p">,</span> <span class="nb">id</span><span class="o">=</span><span class="nb">id</span><span class="p">,</span> <span class="n">hostname</span><span class="o">=</span> <span class="n">hostname</span><span class="p">))</span> </pre></div> </div> <p>In Python, the formatting and printing of a string with multiple variables in a single line of code of standard width is noticeably harder and more verbose, with indentation exacerbating the issue.</p> <p>For use cases such as smaller projects, systems programming, shell script replacements, and even one-liners, where message formatting complexity has yet to be encapsulated, this verbosity has likely lead a significant number of developers and administrators to choose other languages over the years.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <section id="goals"> <h3><a class="toc-backref" href="#goals" role="doc-backlink">Goals</a></h3> <p>The design goals of format strings are as follows:</p> <ol class="arabic simple"> <li>Eliminate need to pass variables manually.</li> <li>Eliminate repetition of identifiers and redundant parentheses.</li> <li>Reduce awkward syntax, punctuation characters, and visual noise.</li> <li>Improve readability and eliminate mismatch errors, by preferring named parameters to positional arguments.</li> <li>Avoid need for <code class="docutils literal notranslate"><span class="pre">locals()</span></code> and <code class="docutils literal notranslate"><span class="pre">globals()</span></code> usage, instead parsing the given string for named parameters, then passing them automatically. <a class="footnote-reference brackets" href="#id17" id="id4">[2]</a> <a class="footnote-reference brackets" href="#id18" id="id5">[3]</a></li> </ol> </section> <section id="limitations"> <h3><a class="toc-backref" href="#limitations" role="doc-backlink">Limitations</a></h3> <p>In contrast to other languages that take design cues from Unix and its shells, and in common with Javascript, Python specified both single (<code class="docutils literal notranslate"><span class="pre">'</span></code>) and double (<code class="docutils literal notranslate"><span class="pre">"</span></code>) ASCII quote characters to enclose strings. It is not reasonable to choose one of them now to enable interpolation, while leaving the other for uninterpolated strings. Other characters, such as the “Backtick” (or grave accent <code class="docutils literal notranslate"><span class="pre">`</span></code>) are also <a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2007-January/000054.html">constrained by history</a> as a shortcut for <code class="docutils literal notranslate"><span class="pre">repr()</span></code>.</p> <p>This leaves a few remaining options for the design of such a feature:</p> <ul class="simple"> <li>An operator, as in printf-style string formatting via <code class="docutils literal notranslate"><span class="pre">%</span></code>.</li> <li>A class, such as <code class="docutils literal notranslate"><span class="pre">string.Template()</span></code>.</li> <li>A method or function, such as <code class="docutils literal notranslate"><span class="pre">str.format()</span></code>.</li> <li>New syntax, or</li> <li>A new string prefix marker, such as the well-known <code class="docutils literal notranslate"><span class="pre">r''</span></code> or <code class="docutils literal notranslate"><span class="pre">u''</span></code>.</li> </ul> <p>The first three options above are mature. Each has specific use cases and drawbacks, yet also suffer from the verbosity and visual noise mentioned previously. All options are discussed in the next sections.</p> </section> <section id="background"> <h3><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h3> <p>Formatted strings build on several existing techniques and proposals and what we’ve collectively learned from them. In keeping with the design goals of readability and error-prevention, the following examples therefore use named, not positional arguments.</p> <p>Let’s assume we have the following dictionary, and would like to print out its items as an informative string for end users:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'user'</span><span class="p">:</span> <span class="s1">'nobody'</span><span class="p">,</span> <span class="s1">'id'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span> <span class="s1">'hostname'</span><span class="p">:</span> <span class="s1">'darkstar'</span><span class="p">}</span> </pre></div> </div> <section id="printf-style-formatting-via-operator"> <h4><a class="toc-backref" href="#printf-style-formatting-via-operator" role="doc-backlink">Printf-style formatting, via operator</a></h4> <p>This <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting">venerable technique</a> continues to have its uses, such as with byte-based protocols, simplicity in simple cases, and familiarity to many programmers:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="s1">'Hello, user: </span><span class="si">%(user)s</span><span class="s1">, id: </span><span class="si">%(id)s</span><span class="s1">, on host: </span><span class="si">%(hostname)s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">params</span> <span class="go">'Hello, user: nobody, id: 9, on host: darkstar'</span> </pre></div> </div> <p>In this form, considering the prerequisite dictionary creation, the technique is verbose, a tad noisy, yet relatively readable. Additional issues are that an operator can only take one argument besides the original string, meaning multiple parameters must be passed in a tuple or dictionary. Also, it is relatively easy to make an error in the number of arguments passed, the expected type, have a missing key, or forget the trailing type, e.g. (<code class="docutils literal notranslate"><span class="pre">s</span></code> or <code class="docutils literal notranslate"><span class="pre">d</span></code>).</p> </section> <section id="string-template-class"> <h4><a class="toc-backref" href="#string-template-class" role="doc-backlink">string.Template Class</a></h4> <p>The <code class="docutils literal notranslate"><span class="pre">string.Template</span></code> <a class="reference external" href="https://docs.python.org/3/library/string.html#template-strings">class from</a> <a class="pep reference internal" href="../pep-0292/" title="PEP 292 – Simpler String Substitutions">PEP 292</a> (Simpler String Substitutions) is a purposely simplified design, using familiar shell interpolation syntax, with <a class="reference external" href="https://docs.python.org/3/library/string.html#string.Template.safe_substitute">safe-substitution feature</a>, that finds its main use cases in shell and internationalization tools:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Template</span><span class="p">(</span><span class="s1">'Hello, user: $user, id: $</span><span class="si">{id}</span><span class="s1">, on host: $hostname'</span><span class="p">)</span><span class="o">.</span><span class="n">substitute</span><span class="p">(</span><span class="n">params</span><span class="p">)</span> </pre></div> </div> <p>While also verbose, the string itself is readable. Though functionality is limited, it meets its requirements well. It isn’t powerful enough for many cases, and that helps keep inexperienced users out of trouble, as well as avoiding issues with moderately-trusted input (i18n) from third-parties. It unfortunately takes enough code to discourage its use for ad-hoc string interpolation, unless encapsulated in a <a class="reference external" href="http://pythonhosted.org/flufl.i18n/">convenience library</a> such as <code class="docutils literal notranslate"><span class="pre">flufl.i18n</span></code>.</p> </section> <section id="pep-215-string-interpolation"> <h4><a class="toc-backref" href="#pep-215-string-interpolation" role="doc-backlink">PEP 215 - String Interpolation</a></h4> <p><a class="pep reference internal" href="../pep-0215/" title="PEP 215 – String Interpolation">PEP 215</a> was a former proposal of which this one shares a lot in common. Apparently, the world was not ready for it at the time, but considering recent support in a number of other languages, its day may have come.</p> <p>The large number of dollar sign (<code class="docutils literal notranslate"><span class="pre">$</span></code>) characters it included may have led it to resemble Python’s arch-nemesis Perl, and likely contributed to the PEP’s lack of acceptance. It was superseded by the following proposal.</p> </section> <section id="str-format-method"> <h4><a class="toc-backref" href="#str-format-method" role="doc-backlink">str.format() Method</a></h4> <p>The <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> <a class="reference external" href="https://docs.python.org/3/library/string.html#format-string-syntax">syntax of</a> <a class="pep reference internal" href="../pep-3101/" title="PEP 3101 – Advanced String Formatting">PEP 3101</a> is the most recent and modern of the existing options. It is also more powerful and usually easier to read than the others. It avoids many of the drawbacks and limits of the previous techniques.</p> <p>However, due to its necessary function call and parameter passing, it runs from verbose to very verbose in various situations with string literals:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="s1">'Hello, user: </span><span class="si">{user}</span><span class="s1">, id: </span><span class="si">{id}</span><span class="s1">, on host: </span><span class="si">{hostname}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="o">**</span><span class="n">params</span><span class="p">)</span> <span class="go">'Hello, user: nobody, id: 9, on host: darkstar'</span> <span class="go"># when using keyword args, var name shortening sometimes needed to fit :/</span> <span class="gp">>>> </span><span class="s1">'Hello, user: </span><span class="si">{user}</span><span class="s1">, id: </span><span class="si">{id}</span><span class="s1">, on host: </span><span class="si">{host}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">user</span><span class="o">=</span><span class="n">user</span><span class="p">,</span> <span class="go"> id=id,</span> <span class="go"> host=hostname)</span> <span class="go">'Hello, user: nobody, id: 9, on host: darkstar'</span> </pre></div> </div> <p>The verbosity of the method-based approach is illustrated here.</p> </section> <section id="pep-498-literal-string-formatting"> <h4><a class="toc-backref" href="#pep-498-literal-string-formatting" role="doc-backlink">PEP 498 – Literal String Formatting</a></h4> <p><a class="pep reference internal" href="../pep-0498/" title="PEP 498 – Literal String Interpolation">PEP 498</a> defines and discusses format strings, as also described in the <a class="reference internal" href="#abstract">Abstract</a> above.</p> <p>It also, somewhat controversially to those first exposed, introduces the idea that format-strings shall be augmented with support for arbitrary expressions. This is discussed further in the Restricting Syntax section under <a class="reference internal" href="#rejected-ideas">Rejected Ideas</a>.</p> </section> <section id="pep-501-translation-ready-string-interpolation"> <h4><a class="toc-backref" href="#pep-501-translation-ready-string-interpolation" role="doc-backlink">PEP 501 – Translation ready string interpolation</a></h4> <p>The complimentary <a class="pep reference internal" href="../pep-0501/" title="PEP 501 – General purpose template literal strings">PEP 501</a> brings internationalization into the discussion as a first-class concern, with its proposal of the i-prefix, <code class="docutils literal notranslate"><span class="pre">string.Template</span></code> syntax integration compatible with ES6 (Javascript), deferred rendering, and an object return value.</p> </section> </section> <section id="implementations-in-other-languages"> <h3><a class="toc-backref" href="#implementations-in-other-languages" role="doc-backlink">Implementations in Other Languages</a></h3> <p>String interpolation is now well supported by various programming languages used in multiple industries, and is converging into a standard of sorts. It is centered around <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> style syntax in minor variations, with the addition of arbitrary expressions to expand utility.</p> <p>In the <a class="reference internal" href="#motivation">Motivation</a> section it was shown how convenient interpolation syntax existed in Bash, Perl, and Ruby. Let’s take a look at their expression support.</p> <section id="bash"> <h4><a class="toc-backref" href="#bash" role="doc-backlink">Bash</a></h4> <p>Bash supports a number of arbitrary, even recursive constructs inside strings:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="n">echo</span> <span class="s2">"user: $USER, id: $((id + 6)) on host: $(echo is $(hostname))"</span> <span class="n">user</span><span class="p">:</span> <span class="n">nobody</span><span class="p">,</span> <span class="nb">id</span><span class="p">:</span> <span class="mi">15</span> <span class="n">on</span> <span class="n">host</span><span class="p">:</span> <span class="ow">is</span> <span class="n">darkstar</span> </pre></div> </div> <ul class="simple"> <li>Explicit interpolation within double quotes.</li> <li>Direct environment variable access supported.</li> <li>Arbitrary expressions are supported. <a class="footnote-reference brackets" href="#id19" id="id6">[4]</a></li> <li>External process execution and output capture supported. <a class="footnote-reference brackets" href="#id20" id="id7">[5]</a></li> <li>Recursive expressions are supported.</li> </ul> </section> <section id="perl"> <h4><a class="toc-backref" href="#perl" role="doc-backlink">Perl</a></h4> <p>Perl also has arbitrary expression constructs, perhaps not as well known:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">say</span> <span class="s2">"I have @{[$id + 6]} guanacos."</span><span class="p">;</span> <span class="c1"># lists</span> <span class="n">say</span> <span class="s2">"I have ${\($id + 6)} guanacos."</span><span class="p">;</span> <span class="c1"># scalars</span> <span class="n">say</span> <span class="s2">"Hello { @names.join(', ') } how are you?"</span><span class="p">;</span> <span class="c1"># Perl 6 version</span> </pre></div> </div> <ul class="simple"> <li>Explicit interpolation within double quotes.</li> <li>Arbitrary expressions are supported. <a class="footnote-reference brackets" href="#id21" id="id8">[6]</a> <a class="footnote-reference brackets" href="#id22" id="id9">[7]</a></li> </ul> </section> <section id="ruby"> <h4><a class="toc-backref" href="#ruby" role="doc-backlink">Ruby</a></h4> <p>Ruby allows arbitrary expressions in its interpolated strings:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">puts</span> <span class="s2">"One plus one is two: #{1 + 1}</span><span class="se">\n</span><span class="s2">"</span> </pre></div> </div> <ul class="simple"> <li>Explicit interpolation within double quotes.</li> <li>Arbitrary expressions are supported. <a class="footnote-reference brackets" href="#id23" id="id10">[8]</a> <a class="footnote-reference brackets" href="#id24" id="id11">[9]</a></li> <li>Possible to change delimiter chars with <code class="docutils literal notranslate"><span class="pre">%</span></code>.</li> <li>See the Reference Implementation(s) section for an implementation in Python.</li> </ul> </section> <section id="others"> <h4><a class="toc-backref" href="#others" role="doc-backlink">Others</a></h4> <p>Let’s look at some less-similar modern languages recently implementing string interpolation.</p> </section> <section id="scala"> <h4><a class="toc-backref" href="#scala" role="doc-backlink">Scala</a></h4> <p><a class="reference external" href="http://docs.scala-lang.org/overviews/core/string-interpolation.html">Scala interpolation</a> is directed through string prefixes. Each prefix has a different result:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span><span class="s2">"Hello, $name ${1 + 1}"</span> <span class="c1"># arbitrary</span> <span class="sa">f</span><span class="s2">"$name%s is $height%2.2f meters tall"</span> <span class="c1"># printf-style</span> <span class="n">raw</span><span class="s2">"a</span><span class="se">\n</span><span class="s2">b"</span> <span class="c1"># raw, like r''</span> </pre></div> </div> <p>These prefixes may also be implemented by the user, by extending Scala’s <code class="docutils literal notranslate"><span class="pre">StringContext</span></code> class.</p> <ul class="simple"> <li>Explicit interpolation within double quotes with literal prefix.</li> <li>User implemented prefixes supported.</li> <li>Arbitrary expressions are supported.</li> </ul> </section> <section id="es6-javascript"> <h4><a class="toc-backref" href="#es6-javascript" role="doc-backlink">ES6 (Javascript)</a></h4> <p>Designers of <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings">Template strings</a> faced the same issue as Python where single and double quotes were taken. Unlike Python however, “backticks” were not. Despite <a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2007-January/000054.html">their issues</a>, they were chosen as part of the ECMAScript 2015 (ES6) standard:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`); </pre></div> </div> <p>Custom prefixes are also supported by implementing a function the same name as the tag:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>function tag(strings, ...values) { console.log(strings.raw[0]); // raw string is also available return "Bazinga!"; } tag`Hello ${ a + b } world ${ a * b}`; </pre></div> </div> <ul class="simple"> <li>Explicit interpolation within backticks.</li> <li>User implemented prefixes supported.</li> <li>Arbitrary expressions are supported.</li> </ul> </section> <section id="c-version-6"> <h4><a class="toc-backref" href="#c-version-6" role="doc-backlink">C#, Version 6</a></h4> <p>C# has a useful new <a class="reference external" href="https://msdn.microsoft.com/en-us/library/Dn961160.aspx">interpolation feature</a> as well, with some ability to <a class="reference external" href="http://www.thomaslevesque.com/2015/02/24/customizing-string-interpolation-in-c-6/">customize interpolation</a> via the <code class="docutils literal notranslate"><span class="pre">IFormattable</span></code> interface:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$"{person.Name, 20} is {person.Age:D3} year{(p.Age == 1 ? "" : "s")} old."; </pre></div> </div> <ul class="simple"> <li>Explicit interpolation with double quotes and <code class="docutils literal notranslate"><span class="pre">$</span></code> prefix.</li> <li>Custom interpolations are available.</li> <li>Arbitrary expressions are supported.</li> </ul> </section> <section id="apple-s-swift"> <h4><a class="toc-backref" href="#apple-s-swift" role="doc-backlink">Apple’s Swift</a></h4> <p>Arbitrary <a class="reference external" href="https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID292">interpolation under Swift</a> is available on all strings:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">let</span> <span class="n">multiplier</span> <span class="o">=</span> <span class="mi">3</span> <span class="n">let</span> <span class="n">message</span> <span class="o">=</span> <span class="s2">"\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"</span> <span class="o">//</span> <span class="n">message</span> <span class="ow">is</span> <span class="s2">"3 times 2.5 is 7.5"</span> </pre></div> </div> <ul class="simple"> <li>Implicit interpolation with double quotes.</li> <li>Arbitrary expressions are supported.</li> <li>Cannot contain CR/LF.</li> </ul> </section> <section id="additional-examples"> <h4><a class="toc-backref" href="#additional-examples" role="doc-backlink">Additional examples</a></h4> <p>A number of additional examples of string interpolation may be <a class="reference external" href="https://en.wikipedia.org/wiki/String_interpolation#Examples">found at Wikipedia</a>.</p> <p>Now that background and history have been covered, let’s continue on for a solution.</p> </section> </section> <section id="new-syntax"> <h3><a class="toc-backref" href="#new-syntax" role="doc-backlink">New Syntax</a></h3> <p>This should be an option of last resort, as every new syntax feature has a cost in terms of real-estate in a brain it inhabits. There is however one alternative left on our list of possibilities, which follows.</p> </section> <section id="new-string-prefix"> <h3><a class="toc-backref" href="#new-string-prefix" role="doc-backlink">New String Prefix</a></h3> <p>Given the history of string formatting in Python and backwards-compatibility, implementations in other languages, avoidance of new syntax unless necessary, an acceptable design is reached through elimination rather than unique insight. Therefore, marking interpolated string literals with a string prefix is chosen.</p> <p>We also choose an expression syntax that reuses and builds on the strongest of the existing choices, <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> to avoid further duplication of functionality:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">location</span> <span class="o">=</span> <span class="s1">'World'</span> <span class="gp">>>> </span><span class="sa">f</span><span class="s1">'Hello, </span><span class="si">{</span><span class="n">location</span><span class="si">}</span><span class="s1"> !'</span> <span class="c1"># new prefix: f''</span> <span class="go">'Hello, World !' # interpolated result</span> </pre></div> </div> <p><a class="pep reference internal" href="../pep-0498/" title="PEP 498 – Literal String Interpolation">PEP 498</a> – Literal String Formatting, delves into the mechanics and implementation of this design.</p> </section> </section> <section id="additional-topics"> <h2><a class="toc-backref" href="#additional-topics" role="doc-backlink">Additional Topics</a></h2> <section id="safety"> <h3><a class="toc-backref" href="#safety" role="doc-backlink">Safety</a></h3> <p>In this section we will describe the safety situation and precautions taken in support of format-strings.</p> <ol class="arabic"> <li>Only string literals have been considered for format-strings, not variables to be taken as input or passed around, making external attacks difficult to accomplish.<p><code class="docutils literal notranslate"><span class="pre">str.format()</span></code> and alternatives <a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034729.html">already handle</a> this use-case.</p> </li> <li>Neither <code class="docutils literal notranslate"><span class="pre">locals()</span></code> nor <code class="docutils literal notranslate"><span class="pre">globals()</span></code> are necessary nor used during the transformation, avoiding leakage of information.</li> <li>To eliminate complexity as well as <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code> (s) due to recursion depth, recursive interpolation is not supported.</li> </ol> <p>However, mistakes or malicious code could be missed inside string literals. Though that can be said of code in general, that these expressions are inside strings means they are a bit more likely to be obscured.</p> <section id="mitigation-via-tools"> <h4><a class="toc-backref" href="#mitigation-via-tools" role="doc-backlink">Mitigation via Tools</a></h4> <p>The idea is that tools or linters such as pyflakes, pylint, or Pycharm, may check inside strings with expressions and mark them up appropriately. As this is a common task with programming languages today, multi-language tools won’t have to implement this feature solely for Python, significantly shortening time to implementation.</p> <p>Farther in the future, strings might also be checked for constructs that exceed the safety policy of a project.</p> </section> </section> <section id="style-guide-precautions"> <h3><a class="toc-backref" href="#style-guide-precautions" role="doc-backlink">Style Guide/Precautions</a></h3> <p>As arbitrary expressions may accomplish anything a Python expression is able to, it is highly recommended to avoid constructs inside format-strings that could cause side effects.</p> <p>Further guidelines may be written once usage patterns and true problems are known.</p> </section> <section id="reference-implementation-s"> <h3><a class="toc-backref" href="#reference-implementation-s" role="doc-backlink">Reference Implementation(s)</a></h3> <p>The <a class="reference external" href="https://pypi.python.org/pypi/say/">say module on PyPI</a> implements string interpolation as described here with the small burden of a callable interface:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>> pip install say from say import say nums = list(range(4)) say("Nums has {len(nums)} items: {nums}") </pre></div> </div> <p>A Python implementation of Ruby interpolation <a class="reference external" href="https://github.com/syrusakbary/interpy">is also available</a>. It uses the codecs module to do its work:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>> pip install interpy # coding: interpy location = 'World' print("Hello #{location}.") </pre></div> </div> </section> <section id="backwards-compatibility"> <h3><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h3> <p>By using existing syntax and avoiding current or historical features, format strings were designed so as to not interfere with existing code and are not expected to cause any issues.</p> </section> <section id="postponed-ideas"> <h3><a class="toc-backref" href="#postponed-ideas" role="doc-backlink">Postponed Ideas</a></h3> <section id="internationalization"> <h4><a class="toc-backref" href="#internationalization" role="doc-backlink">Internationalization</a></h4> <p>Though it was highly desired to integrate internationalization support, (see <a class="pep reference internal" href="../pep-0501/" title="PEP 501 – General purpose template literal strings">PEP 501</a>), the finer details diverge at almost every point, making a common solution unlikely: <a class="footnote-reference brackets" href="#id30" id="id12">[15]</a></p> <ul class="simple"> <li>Use-cases differ</li> <li>Compile vs. run-time tasks</li> <li>Interpolation syntax needs</li> <li>Intended audience</li> <li>Security policy</li> </ul> </section> </section> <section id="rejected-ideas"> <h3><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h3> <section id="restricting-syntax-to-str-format-only"> <h4><a class="toc-backref" href="#restricting-syntax-to-str-format-only" role="doc-backlink">Restricting Syntax to <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> Only</a></h4> <p>The common <a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-August/034913.html">arguments against</a> support of arbitrary expressions were:</p> <ol class="arabic simple"> <li><a class="reference external" href="https://en.wikipedia.org/wiki/You_aren't_gonna_need_it">YAGNI</a>, “You aren’t gonna need it.”</li> <li>The feature is not congruent with historical Python conservatism.</li> <li>Postpone - can implement in a future version if need is demonstrated.</li> </ol> <p>Support of only <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> syntax however, was deemed not enough of a solution to the problem. Often a simple length or increment of an object, for example, is desired before printing.</p> <p>It can be seen in the <a class="reference internal" href="#implementations-in-other-languages">Implementations in Other Languages</a> section that the developer community at large tends to agree. String interpolation with arbitrary expressions is becoming an industry standard in modern languages due to its utility.</p> </section> <section id="additional-custom-string-prefixes"> <h4><a class="toc-backref" href="#additional-custom-string-prefixes" role="doc-backlink">Additional/Custom String-Prefixes</a></h4> <p>As seen in the <a class="reference internal" href="#implementations-in-other-languages">Implementations in Other Languages</a> section, many modern languages have extensible string prefixes with a common interface. This could be a way to generalize and reduce lines of code in common situations. Examples are found in ES6 (Javascript), Scala, Nim, and C# (to a lesser extent). This was rejected by the BDFL. <a class="footnote-reference brackets" href="#id29" id="id13">[14]</a></p> </section> <section id="automated-escaping-of-input-variables"> <h4><a class="toc-backref" href="#automated-escaping-of-input-variables" role="doc-backlink">Automated Escaping of Input Variables</a></h4> <p>While helpful in some cases, this was thought to create too much uncertainty of when and where string expressions could be used safely or not. The concept was also difficult to describe to others. <a class="footnote-reference brackets" href="#id27" id="id14">[12]</a></p> <p>Always consider format string variables to be unescaped, unless the developer has explicitly escaped them.</p> </section> <section id="environment-access-and-command-substitution"> <h4><a class="toc-backref" href="#environment-access-and-command-substitution" role="doc-backlink">Environment Access and Command Substitution</a></h4> <p>For systems programming and shell-script replacements, it would be useful to handle environment variables and capture output of commands directly in an expression string. This was rejected as not important enough, and looking too much like bash/perl, which could encourage bad habits. <a class="footnote-reference brackets" href="#id28" id="id15">[13]</a></p> </section> </section> </section> <section id="acknowledgements"> <h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2> <ul class="simple"> <li>Eric V. Smith for the authoring and implementation of <a class="pep reference internal" href="../pep-0498/" title="PEP 498 – Literal String Interpolation">PEP 498</a>.</li> <li>Everyone on the python-ideas mailing list for rejecting the various crazy ideas that came up, helping to keep the final design in focus.</li> </ul> </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="id16" role="doc-footnote"> <dt class="label" id="id16">[<a href="#id3">1</a>]</dt> <dd>Briefer String Format (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034659.html">https://mail.python.org/pipermail/python-ideas/2015-July/034659.html</a>)</aside> <aside class="footnote brackets" id="id17" role="doc-footnote"> <dt class="label" id="id17">[<a href="#id4">2</a>]</dt> <dd>Briefer String Format (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-July/034669.html">https://mail.python.org/pipermail/python-ideas/2015-July/034669.html</a>)</aside> <aside class="footnote brackets" id="id18" role="doc-footnote"> <dt class="label" id="id18">[<a href="#id5">3</a>]</dt> <dd>Briefer String Format (<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="id19" role="doc-footnote"> <dt class="label" id="id19">[<a href="#id6">4</a>]</dt> <dd>Bash Docs (<a class="reference external" href="https://tldp.org/LDP/abs/html/arithexp.html">https://tldp.org/LDP/abs/html/arithexp.html</a>)</aside> <aside class="footnote brackets" id="id20" role="doc-footnote"> <dt class="label" id="id20">[<a href="#id7">5</a>]</dt> <dd>Bash Docs (<a class="reference external" href="https://tldp.org/LDP/abs/html/commandsub.html">https://tldp.org/LDP/abs/html/commandsub.html</a>)</aside> <aside class="footnote brackets" id="id21" role="doc-footnote"> <dt class="label" id="id21">[<a href="#id8">6</a>]</dt> <dd>Perl Cookbook (<a class="reference external" href="https://docstore.mik.ua/orelly/perl/cookbook/ch01_11.htm">https://docstore.mik.ua/orelly/perl/cookbook/ch01_11.htm</a>)</aside> <aside class="footnote brackets" id="id22" role="doc-footnote"> <dt class="label" id="id22">[<a href="#id9">7</a>]</dt> <dd>Perl Docs (<a class="reference external" href="https://web.archive.org/web/20121025185907/https://perl6maven.com/perl6-scalar-array-and-hash-interpolation">https://web.archive.org/web/20121025185907/https://perl6maven.com/perl6-scalar-array-and-hash-interpolation</a>)</aside> <aside class="footnote brackets" id="id23" role="doc-footnote"> <dt class="label" id="id23">[<a href="#id10">8</a>]</dt> <dd>Ruby Docs (<a class="reference external" href="http://ruby-doc.org/core-2.1.1/doc/syntax/literals_rdoc.html#label-Strings">http://ruby-doc.org/core-2.1.1/doc/syntax/literals_rdoc.html#label-Strings</a>)</aside> <aside class="footnote brackets" id="id24" role="doc-footnote"> <dt class="label" id="id24">[<a href="#id11">9</a>]</dt> <dd>Ruby Docs (<a class="reference external" href="https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Interpolation">https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Interpolation</a>)</aside> <aside class="footnote brackets" id="id25" role="doc-footnote"> <dt class="label" id="id25">[<a href="#id1">10</a>]</dt> <dd>Python Str.Format Syntax (<a class="reference external" href="https://docs.python.org/3.6/library/string.html#format-string-syntax">https://docs.python.org/3.6/library/string.html#format-string-syntax</a>)</aside> <aside class="footnote brackets" id="id26" role="doc-footnote"> <dt class="label" id="id26">[<a href="#id2">11</a>]</dt> <dd>Python Format-Spec Mini Language (<a class="reference external" href="https://docs.python.org/3.6/library/string.html#format-specification-mini-language">https://docs.python.org/3.6/library/string.html#format-specification-mini-language</a>)</aside> <aside class="footnote brackets" id="id27" role="doc-footnote"> <dt class="label" id="id27">[<a href="#id14">12</a>]</dt> <dd>Escaping of Input Variables (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-August/035532.html">https://mail.python.org/pipermail/python-ideas/2015-August/035532.html</a>)</aside> <aside class="footnote brackets" id="id28" role="doc-footnote"> <dt class="label" id="id28">[<a href="#id15">13</a>]</dt> <dd>Environment Access and Command Substitution (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-August/035554.html">https://mail.python.org/pipermail/python-ideas/2015-August/035554.html</a>)</aside> <aside class="footnote brackets" id="id29" role="doc-footnote"> <dt class="label" id="id29">[<a href="#id13">14</a>]</dt> <dd>Extensible String Prefixes (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-August/035336.html">https://mail.python.org/pipermail/python-ideas/2015-August/035336.html</a>)</aside> <aside class="footnote brackets" id="id30" role="doc-footnote"> <dt class="label" id="id30">[<a href="#id12">15</a>]</dt> <dd>Literal String Formatting (<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-August/141289.html">https://mail.python.org/pipermail/python-dev/2015-August/141289.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-0502.rst">https://github.com/python/peps/blob/main/peps/pep-0502.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0502.rst">2025-02-01 08:55:40 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="#pep-status">PEP Status</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#goals">Goals</a></li> <li><a class="reference internal" href="#limitations">Limitations</a></li> <li><a class="reference internal" href="#background">Background</a><ul> <li><a class="reference internal" href="#printf-style-formatting-via-operator">Printf-style formatting, via operator</a></li> <li><a class="reference internal" href="#string-template-class">string.Template Class</a></li> <li><a class="reference internal" href="#pep-215-string-interpolation">PEP 215 - String Interpolation</a></li> <li><a class="reference internal" href="#str-format-method">str.format() Method</a></li> <li><a class="reference internal" href="#pep-498-literal-string-formatting">PEP 498 – Literal String Formatting</a></li> <li><a class="reference internal" href="#pep-501-translation-ready-string-interpolation">PEP 501 – Translation ready string interpolation</a></li> </ul> </li> <li><a class="reference internal" href="#implementations-in-other-languages">Implementations in Other Languages</a><ul> <li><a class="reference internal" href="#bash">Bash</a></li> <li><a class="reference internal" href="#perl">Perl</a></li> <li><a class="reference internal" href="#ruby">Ruby</a></li> <li><a class="reference internal" href="#others">Others</a></li> <li><a class="reference internal" href="#scala">Scala</a></li> <li><a class="reference internal" href="#es6-javascript">ES6 (Javascript)</a></li> <li><a class="reference internal" href="#c-version-6">C#, Version 6</a></li> <li><a class="reference internal" href="#apple-s-swift">Apple’s Swift</a></li> <li><a class="reference internal" href="#additional-examples">Additional examples</a></li> </ul> </li> <li><a class="reference internal" href="#new-syntax">New Syntax</a></li> <li><a class="reference internal" href="#new-string-prefix">New String Prefix</a></li> </ul> </li> <li><a class="reference internal" href="#additional-topics">Additional Topics</a><ul> <li><a class="reference internal" href="#safety">Safety</a><ul> <li><a class="reference internal" href="#mitigation-via-tools">Mitigation via Tools</a></li> </ul> </li> <li><a class="reference internal" href="#style-guide-precautions">Style Guide/Precautions</a></li> <li><a class="reference internal" href="#reference-implementation-s">Reference Implementation(s)</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#postponed-ideas">Postponed Ideas</a><ul> <li><a class="reference internal" href="#internationalization">Internationalization</a></li> </ul> </li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#restricting-syntax-to-str-format-only">Restricting Syntax to <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> Only</a></li> <li><a class="reference internal" href="#additional-custom-string-prefixes">Additional/Custom String-Prefixes</a></li> <li><a class="reference internal" href="#automated-escaping-of-input-variables">Automated Escaping of Input Variables</a></li> <li><a class="reference internal" href="#environment-access-and-command-substitution">Environment Access and Command Substitution</a></li> </ul> </li> </ul> </li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</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-0502.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>