CINXE.COM
PEP 214 – Extended Print Statement | 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 214 – Extended Print Statement | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0214/"> <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 214 – Extended Print Statement | peps.python.org'> <meta property="og:description" content="This PEP describes a syntax to extend the standard ‘print’ statement so that it can be used to print to any file-like object, instead of the default sys.stdout. This PEP tracks the status and ownership of this feature. It contains a description of the..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0214/"> <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="This PEP describes a syntax to extend the standard ‘print’ statement so that it can be used to print to any file-like object, instead of the default sys.stdout. This PEP tracks the status and ownership of this feature. It contains a description of the..."> <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 214</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 214 – Extended Print Statement</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Barry Warsaw <barry at python.org></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">24-Jul-2000</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">2.0</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even">16-Aug-2000</dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#introduction">Introduction</a></li> <li><a class="reference internal" href="#proposal">Proposal</a></li> <li><a class="reference internal" href="#justification">Justification</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#alternative-approaches">Alternative Approaches</a></li> <li><a class="reference internal" href="#more-justification-by-the-bdfl">More Justification by the BDFL</a></li> <li><a class="reference internal" href="#references">References</a></li> </ul> </details></section> <section id="introduction"> <h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2> <p>This PEP describes a syntax to extend the standard ‘print’ statement so that it can be used to print to any file-like object, instead of the default <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature. This PEP summarizes discussions held in mailing list forums, and provides URLs for further information, where appropriate. The CVS revision history of this file contains the definitive historical record.</p> </section> <section id="proposal"> <h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2> <p>This proposal introduces a syntax extension to the print statement, which allows the programmer to optionally specify the output file target. An example usage is as follows:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">>></span> <span class="n">mylogfile</span><span class="p">,</span> <span class="s1">'this message goes to my log file'</span> </pre></div> </div> <p>Formally, the syntax of the extended print statement is:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">print_stmt</span><span class="p">:</span> <span class="o">...</span> <span class="o">|</span> <span class="s1">'>>'</span> <span class="n">test</span> <span class="p">[</span> <span class="p">(</span><span class="s1">','</span> <span class="n">test</span><span class="p">)</span><span class="o">+</span> <span class="p">[</span><span class="s1">','</span><span class="p">]</span> <span class="p">]</span> <span class="p">)</span> </pre></div> </div> <p>where the ellipsis indicates the original print_stmt syntax unchanged. In the extended form, the expression just after >> must yield an object with a <code class="docutils literal notranslate"><span class="pre">write()</span></code> method (i.e. a file-like object). Thus these two statements are equivalent:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="s1">'hello world'</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="s1">'hello world'</span> </pre></div> </div> <p>As are these two statements:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> </pre></div> </div> <p>These two statements are syntax errors:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="p">,</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> </pre></div> </div> </section> <section id="justification"> <h2><a class="toc-backref" href="#justification" role="doc-backlink">Justification</a></h2> <p>‘print’ is a Python keyword and introduces the print statement as described in section 6.6 of the language reference manual <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a>. The print statement has a number of features:</p> <ul class="simple"> <li>it auto-converts the items to strings</li> <li>it inserts spaces between items automatically</li> <li>it appends a newline unless the statement ends in a comma</li> </ul> <p>The formatting that the print statement performs is limited; for more control over the output, a combination of <code class="docutils literal notranslate"><span class="pre">sys.stdout.write()</span></code>, and string interpolation can be used.</p> <p>The print statement by definition outputs to <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>. More specifically, <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> must be a file-like object with a <code class="docutils literal notranslate"><span class="pre">write()</span></code> method, but it can be rebound to redirect output to files other than specifically standard output. A typical idiom is:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">save_stdout</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="k">try</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">mylogfile</span> <span class="nb">print</span> <span class="s1">'this message goes to my log file'</span> <span class="k">finally</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">save_stdout</span> </pre></div> </div> <p>The problem with this approach is that the binding is global, and so affects every statement inside the try: clause. For example, if we added a call to a function that actually did want to print to stdout, this output too would get redirected to the logfile.</p> <p>This approach is also very inconvenient for interleaving prints to various output streams, and complicates coding in the face of legitimate try/except or try/finally clauses.</p> </section> <section id="reference-implementation"> <h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2> <p>A reference implementation, in the form of a patch against the Python 2.0 source tree, is available on SourceForge’s patch manager <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a>. This approach adds two new opcodes, <code class="docutils literal notranslate"><span class="pre">PRINT_ITEM_TO</span></code> and <code class="docutils literal notranslate"><span class="pre">PRINT_NEWLINE_TO</span></code>, which simply pop the file like object off the top of the stack and use it instead of <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> as the output stream.</p> <p>(This reference implementation has been adopted in Python 2.0.)</p> </section> <section id="alternative-approaches"> <h2><a class="toc-backref" href="#alternative-approaches" role="doc-backlink">Alternative Approaches</a></h2> <p>An alternative to this syntax change has been proposed (originally by Moshe Zadka) which requires no syntax changes to Python. A <code class="docutils literal notranslate"><span class="pre">writeln()</span></code> function could be provided (possibly as a builtin), that would act much like extended print, with a few additional features:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">writeln</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kws</span><span class="p">):</span> <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span> <span class="n">file</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="n">sep</span> <span class="o">=</span> <span class="s1">' '</span> <span class="n">end</span> <span class="o">=</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">'</span> <span class="k">if</span> <span class="n">kws</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="s1">'file'</span><span class="p">):</span> <span class="n">file</span> <span class="o">=</span> <span class="n">kws</span><span class="p">[</span><span class="s1">'file'</span><span class="p">]</span> <span class="k">del</span> <span class="n">kws</span><span class="p">[</span><span class="s1">'file'</span><span class="p">]</span> <span class="k">if</span> <span class="n">kws</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="s1">'nl'</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">kws</span><span class="p">[</span><span class="s1">'nl'</span><span class="p">]:</span> <span class="n">end</span> <span class="o">=</span> <span class="s1">' '</span> <span class="k">del</span> <span class="n">kws</span><span class="p">[</span><span class="s1">'nl'</span><span class="p">]</span> <span class="k">if</span> <span class="n">kws</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="s1">'sep'</span><span class="p">):</span> <span class="n">sep</span> <span class="o">=</span> <span class="n">kws</span><span class="p">[</span><span class="s1">'sep'</span><span class="p">]</span> <span class="k">del</span> <span class="n">kws</span><span class="p">[</span><span class="s1">'sep'</span><span class="p">]</span> <span class="k">if</span> <span class="n">kws</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">'unexpected keywords'</span><span class="p">)</span> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">sep</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span> <span class="o">+</span> <span class="n">end</span><span class="p">)</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">writeln()</span></code> takes a three optional keyword arguments. In the context of this proposal, the relevant argument is ‘file’ which can be set to a file-like object with a <code class="docutils literal notranslate"><span class="pre">write()</span></code> method. Thus:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">>></span> <span class="n">mylogfile</span><span class="p">,</span> <span class="s1">'this goes to my log file'</span> </pre></div> </div> <p>would be written as:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">writeln</span><span class="p">(</span><span class="s1">'this goes to my log file'</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">mylogfile</span><span class="p">)</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">writeln()</span></code> has the additional functionality that the keyword argument ‘nl’ is a flag specifying whether to append a newline or not, and an argument ‘sep’ which specifies the separator to output in between each item.</p> </section> <section id="more-justification-by-the-bdfl"> <h2><a class="toc-backref" href="#more-justification-by-the-bdfl" role="doc-backlink">More Justification by the BDFL</a></h2> <p>The proposal has been challenged on the newsgroup. One series of challenges doesn’t like ‘>>’ and would rather see some other symbol.</p> <ul> <li>Challenge: Why not one of these?<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="ow">in</span> <span class="n">stderr</span> <span class="n">items</span><span class="p">,</span><span class="o">....</span> <span class="nb">print</span> <span class="o">+</span> <span class="n">stderr</span> <span class="n">items</span><span class="p">,</span><span class="o">.......</span> <span class="nb">print</span><span class="p">[</span><span class="n">stderr</span><span class="p">]</span> <span class="n">items</span><span class="p">,</span><span class="o">.....</span> <span class="nb">print</span> <span class="n">to</span> <span class="n">stderr</span> <span class="n">items</span><span class="p">,</span><span class="o">.....</span> </pre></div> </div> <p>Response: If we want to use a special symbol (<code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre"><symbol></span></code> expression), the Python parser requires that it is not already a symbol that can start an expression – otherwise it can’t decide which form of print statement is used. (The Python parser is a simple LL(1) or recursive descent parser.)</p> <p>This means that we can’t use the “keyword only in context trick” that was used for “import as”, because an identifier can start an expression. This rules out +stderr, [sterr], and to stderr. It leaves us with binary operator symbols and other miscellaneous symbols that are currently illegal here, such as ‘import’.</p> <p>If I had to choose between ‘print in file’ and ‘print >> file’ I would definitely choose ‘>>’. In part because ‘in’ would be a new invention (I know of no other language that uses it, while ‘>>’ is used in sh, awk, Perl, and C++), in part because ‘>>’, being non-alphabetic, stands out more so is more likely to catch the reader’s attention.</p> </li> <li>Challenge: Why does there have to be a comma between the file and the rest?<p>Response: The comma separating the file from the following expression is necessary! Of course you want the file to be an arbitrary expression, not just a single word. (You definitely want to be able to write <code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">>>sys.stderr</span></code>.) Without the expression the parser wouldn’t be able to distinguish where that expression ends and where the next one begins, e.g.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">>></span><span class="n">i</span> <span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span> <span class="nb">print</span> <span class="o">>></span><span class="n">a</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="mi">2</span> <span class="nb">print</span> <span class="o">>></span><span class="n">f</span> <span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="mi">2</span> </pre></div> </div> </li> <li>Challenge: Why do you need a syntax extension? Why not writeln(file, item, …)?<p>Response: First of all, this is lacking a feature of the print statement: the trailing comma to print which suppresses the final newline. Note that ‘print a,’ still isn’t equivalent to ‘sys.stdout.write(a)’ – print inserts a space between items, and takes arbitrary objects as arguments; <code class="docutils literal notranslate"><span class="pre">write()</span></code> doesn’t insert a space and requires a single string.</p> <p>When you are considering an extension for the print statement, it’s not right to add a function or method that adds a new feature in one dimension (where the output goes) but takes away in another dimension (spaces between items, and the choice of trailing newline or not). We could add a whole slew of methods or functions to deal with the various cases but that seems to add more confusion than necessary, and would only make sense if we were to deprecate the print statement altogether.</p> <p>I feel that this debate is really about whether print should have been a function or method rather than a statement. If you are in the function camp, of course adding special syntax to the existing print statement is not something you like. I suspect the objection to the new syntax comes mostly from people who already think that the print statement was a bad idea. Am I right?</p> <p>About 10 years ago I debated with myself whether to make the most basic from of output a function or a statement; basically I was trying to decide between “print(item, …)” and “print item, …”. I chose to make it a statement because printing needs to be taught very early on, and is very important in the programs that beginners write. Also, because ABC, which lead the way for so many things, made it a statement. In a move that’s typical for the interaction between ABC and Python, I changed the name from WRITE to print, and reversed the convention for adding newlines from requiring extra syntax to add a newline (ABC used trailing slashes to indicate newlines) to requiring extra syntax (the trailing comma) to suppress the newline. I kept the feature that items are separated by whitespace on output.</p> <p>Full example: in ABC,</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">WRITE</span> <span class="mi">1</span> <span class="n">WRITE</span> <span class="mi">2</span><span class="o">/</span> </pre></div> </div> <p>has the same effect as:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">print</span> <span class="mi">2</span> </pre></div> </div> <p>has in Python, outputting in effect “1 2n”.</p> <p>I’m not 100% sure that the choice for a statement was right (ABC had the compelling reason that it used statement syntax for anything with side effects, but Python doesn’t have this convention), but I’m also not convinced that it’s wrong. I certainly like the economy of the print statement. (I’m a rabid Lisp-hater – syntax-wise, not semantics-wise! – and excessive parentheses in syntax annoy me. Don’t ever write <code class="docutils literal notranslate"><span class="pre">return(i)</span> <span class="pre">or</span> <span class="pre">if(x==y):</span></code> in your Python code! :-)</p> <p>Anyway, I’m not ready to deprecate the print statement, and over the years we’ve had many requests for an option to specify the file.</p> </li> <li>Challenge: Why not > instead of >>?<p>Response: To DOS and Unix users, >> suggests “append”, while > suggests “overwrite”; the semantics are closest to append. Also, for C++ programmers, >> and << are I/O operators.</p> </li> <li>Challenge: But in C++, >> is input and << is output!<p>Response: doesn’t matter; C++ clearly took it from Unix and reversed the arrows. The important thing is that for output, the arrow points to the file.</p> </li> <li>Challenge: Surely you can design a <code class="docutils literal notranslate"><span class="pre">println()</span></code> function can do all what <code class="docutils literal notranslate"><span class="pre">print>>file</span></code> can do; why isn’t that enough?<p>Response: I think of this in terms of a simple programming exercise. Suppose a beginning programmer is asked to write a function that prints the tables of multiplication. A reasonable solution is:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</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">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span> <span class="nb">print</span> <span class="n">i</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span> <span class="nb">print</span> </pre></div> </div> <p>Now suppose the second exercise is to add printing to a different file. With the new syntax, the programmer only needs to learn one new thing: <code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">>></span> <span class="pre">file</span></code>, and the answer can be like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">tables</span><span class="p">(</span><span class="n">n</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">stdout</span><span class="p">):</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</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">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">file</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">file</span> </pre></div> </div> <p>With only a print statement and a <code class="docutils literal notranslate"><span class="pre">println()</span></code> function, the programmer first has to learn about <code class="docutils literal notranslate"><span class="pre">println()</span></code>, transforming the original program to using <code class="docutils literal notranslate"><span class="pre">println()</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</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">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span> <span class="n">println</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span><span class="p">)</span> <span class="n">println</span><span class="p">()</span> </pre></div> </div> <p>and <strong>then</strong> about the file keyword argument:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">tables</span><span class="p">(</span><span class="n">n</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">stdout</span><span class="p">):</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</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">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span> <span class="n">println</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</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">stdout</span><span class="p">)</span> <span class="n">println</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">stdout</span><span class="p">)</span> </pre></div> </div> <p>Thus, the transformation path is longer:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="nb">print</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">file</span> </pre></div> </div> <p>vs.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="nb">print</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="n">println</span><span class="p">()</span> <span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="n">println</span><span class="p">(</span><span class="n">file</span><span class="o">=...</span><span class="p">)</span> </pre></div> </div> <p>Note: defaulting the file argument to <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> at compile time is wrong, because it doesn’t work right when the caller assigns to <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> and then uses <code class="docutils literal notranslate"><span class="pre">tables()</span></code> without specifying the file. This is a common problem (and would occur with a <code class="docutils literal notranslate"><span class="pre">println()</span></code> function too). The standard solution so far has been:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">if</span> <span class="n">file</span> <span class="ow">is</span> <span class="kc">None</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">stdout</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</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">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">file</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">file</span> </pre></div> </div> <p>I’ve added a feature to the implementation (which I would also recommend to <code class="docutils literal notranslate"><span class="pre">println()</span></code>) whereby if the file argument is <code class="docutils literal notranslate"><span class="pre">None</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> is automatically used. Thus,</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">>></span> <span class="kc">None</span><span class="p">,</span> <span class="n">foo</span> <span class="n">bar</span> </pre></div> </div> <p>(or, of course, <code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">>></span> <span class="pre">x</span></code> where x is a variable whose value is None) means the same as</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">foo</span><span class="p">,</span> <span class="n">bar</span> </pre></div> </div> <p>and the <code class="docutils literal notranslate"><span class="pre">tables()</span></code> function can be written as follows:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</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">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">file</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span> <span class="nb">print</span> <span class="o">>></span> <span class="n">file</span> </pre></div> </div> </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="id3" role="doc-footnote"> <dt class="label" id="id3">[<a href="#id1">1</a>]</dt> <dd><a class="reference external" href="http://docs.python.org/reference/simple_stmts.html#print">http://docs.python.org/reference/simple_stmts.html#print</a></aside> <aside class="footnote brackets" id="id4" role="doc-footnote"> <dt class="label" id="id4">[<a href="#id2">2</a>]</dt> <dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=100970">http://sourceforge.net/patch/download.php?id=100970</a></aside> </aside> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0214.rst">https://github.com/python/peps/blob/main/peps/pep-0214.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0214.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="#introduction">Introduction</a></li> <li><a class="reference internal" href="#proposal">Proposal</a></li> <li><a class="reference internal" href="#justification">Justification</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#alternative-approaches">Alternative Approaches</a></li> <li><a class="reference internal" href="#more-justification-by-the-bdfl">More Justification by the BDFL</a></li> <li><a class="reference internal" href="#references">References</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0214.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>