706 lines
62 KiB
HTML
706 lines
62 KiB
HTML
|
||
<!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 3104 – Access to Names in Outer Scopes | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-3104/">
|
||
<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 3104 – Access to Names in Outer Scopes | peps.python.org'>
|
||
<meta property="og:description" content="In most languages that support nested scopes, code can refer to or rebind (assign to) any name in the nearest enclosing scope. Currently, Python code can refer to a name in any enclosing scope, but it can only rebind names in two scopes: the local scope...">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-3104/">
|
||
<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="In most languages that support nested scopes, code can refer to or rebind (assign to) any name in the nearest enclosing scope. Currently, Python code can refer to a name in any enclosing scope, but it can only rebind names in two scopes: the local scope...">
|
||
<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 3104</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 3104 – Access to Names in Outer Scopes</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Ka-Ping Yee <ping at zesty.ca></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">12-Oct-2006</dd>
|
||
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-odd">3.0</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even"><p></p></dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#other-languages">Other Languages</a><ul>
|
||
<li><a class="reference internal" href="#javascript-perl-scheme-smalltalk-gnu-c-c-2-0">JavaScript, Perl, Scheme, Smalltalk, GNU C, C# 2.0</a></li>
|
||
<li><a class="reference internal" href="#ruby-as-of-1-8">Ruby (as of 1.8)</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#overview-of-proposals">Overview of Proposals</a><ul>
|
||
<li><a class="reference internal" href="#new-syntax-in-the-binding-outer-scope">New Syntax in the Binding (Outer) Scope</a><ul>
|
||
<li><a class="reference internal" href="#scope-override-declaration">Scope Override Declaration</a></li>
|
||
<li><a class="reference internal" href="#required-variable-declaration">Required Variable Declaration</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#new-syntax-in-the-referring-inner-scope">New Syntax in the Referring (Inner) Scope</a><ul>
|
||
<li><a class="reference internal" href="#outer-reference-expression">Outer Reference Expression</a></li>
|
||
<li><a class="reference internal" href="#rebinding-operator">Rebinding Operator</a></li>
|
||
<li><a class="reference internal" href="#id15">Scope Override Declaration</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#proposed-solution">Proposed Solution</a></li>
|
||
<li><a class="reference internal" href="#backward-compatibility">Backward Compatibility</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</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>In most languages that support nested scopes, code can refer to or
|
||
rebind (assign to) any name in the nearest enclosing scope.
|
||
Currently, Python code can refer to a name in any enclosing scope,
|
||
but it can only rebind names in two scopes: the local scope (by
|
||
simple assignment) or the module-global scope (using a <code class="docutils literal notranslate"><span class="pre">global</span></code>
|
||
declaration).</p>
|
||
<p>This limitation has been raised many times on the Python-Dev mailing
|
||
list and elsewhere, and has led to extended discussion and many
|
||
proposals for ways to remove this limitation. This PEP summarizes
|
||
the various alternatives that have been suggested, together with
|
||
advantages and disadvantages that have been mentioned for each.</p>
|
||
</section>
|
||
<section id="rationale">
|
||
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
||
<p>Before version 2.1, Python’s treatment of scopes resembled that of
|
||
standard C: within a file there were only two levels of scope, global
|
||
and local. In C, this is a natural consequence of the fact that
|
||
function definitions cannot be nested. But in Python, though
|
||
functions are usually defined at the top level, a function definition
|
||
can be executed anywhere. This gave Python the syntactic appearance
|
||
of nested scoping without the semantics, and yielded inconsistencies
|
||
that were surprising to some programmers – for example, a recursive
|
||
function that worked at the top level would cease to work when moved
|
||
inside another function, because the recursive function’s own name
|
||
would no longer be visible in its body’s scope. This violates the
|
||
intuition that a function should behave consistently when placed in
|
||
different contexts. Here’s an example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">enclosing_function</span><span class="p">():</span>
|
||
<span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">2</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="mi">1</span>
|
||
<span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="n">factorial</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="c1"># fails with NameError</span>
|
||
<span class="nb">print</span> <span class="n">factorial</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Python 2.1 moved closer to static nested scoping by making visible
|
||
the names bound in all enclosing scopes (see <a class="pep reference internal" href="../pep-0227/" title="PEP 227 – Statically Nested Scopes">PEP 227</a>). This change
|
||
makes the above code example work as expected. However, because any
|
||
assignment to a name implicitly declares that name to be local, it is
|
||
impossible to rebind a name in an outer scope (except when a
|
||
<code class="docutils literal notranslate"><span class="pre">global</span></code> declaration forces the name to be global). Thus, the
|
||
following code, intended to display a number that can be incremented
|
||
and decremented by clicking buttons, doesn’t work as someone familiar
|
||
with lexical scoping might expect:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">make_scoreboard</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">score</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
|
||
<span class="n">label</span> <span class="o">=</span> <span class="n">Label</span><span class="p">(</span><span class="n">frame</span><span class="p">)</span>
|
||
<span class="n">label</span><span class="o">.</span><span class="n">pack</span><span class="p">()</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="p">[</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">]:</span>
|
||
<span class="k">def</span> <span class="nf">increment</span><span class="p">(</span><span class="n">step</span><span class="o">=</span><span class="n">i</span><span class="p">):</span>
|
||
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o">+</span> <span class="n">step</span> <span class="c1"># fails with UnboundLocalError</span>
|
||
<span class="n">label</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">score</span>
|
||
<span class="n">button</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s1">'</span><span class="si">%+d</span><span class="s1">'</span> <span class="o">%</span> <span class="n">i</span><span class="p">,</span> <span class="n">command</span><span class="o">=</span><span class="n">increment</span><span class="p">)</span>
|
||
<span class="n">button</span><span class="o">.</span><span class="n">pack</span><span class="p">()</span>
|
||
<span class="k">return</span> <span class="n">label</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Python syntax doesn’t provide a way to indicate that the name
|
||
<code class="docutils literal notranslate"><span class="pre">score</span></code> mentioned in <code class="docutils literal notranslate"><span class="pre">increment</span></code> refers to the variable <code class="docutils literal notranslate"><span class="pre">score</span></code>
|
||
bound in <code class="docutils literal notranslate"><span class="pre">make_scoreboard</span></code>, not a local variable in <code class="docutils literal notranslate"><span class="pre">increment</span></code>.
|
||
Users and developers of Python have expressed an interest in removing
|
||
this limitation so that Python can have the full flexibility of the
|
||
Algol-style scoping model that is now standard in many programming
|
||
languages, including JavaScript, Perl, Ruby, Scheme, Smalltalk,
|
||
C with GNU extensions, and C# 2.0.</p>
|
||
<p>It has been argued that such a feature isn’t necessary, because
|
||
a rebindable outer variable can be simulated by wrapping it in a
|
||
mutable object:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Namespace</span><span class="p">:</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="k">def</span> <span class="nf">make_scoreboard</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">score</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
|
||
<span class="n">ns</span> <span class="o">=</span> <span class="n">Namespace</span><span class="p">()</span>
|
||
<span class="n">ns</span><span class="o">.</span><span class="n">score</span> <span class="o">=</span> <span class="mi">0</span>
|
||
<span class="n">label</span> <span class="o">=</span> <span class="n">Label</span><span class="p">(</span><span class="n">frame</span><span class="p">)</span>
|
||
<span class="n">label</span><span class="o">.</span><span class="n">pack</span><span class="p">()</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="p">[</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">]:</span>
|
||
<span class="k">def</span> <span class="nf">increment</span><span class="p">(</span><span class="n">step</span><span class="o">=</span><span class="n">i</span><span class="p">):</span>
|
||
<span class="n">ns</span><span class="o">.</span><span class="n">score</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">score</span> <span class="o">+</span> <span class="n">step</span>
|
||
<span class="n">label</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">score</span>
|
||
<span class="n">button</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s1">'</span><span class="si">%+d</span><span class="s1">'</span> <span class="o">%</span> <span class="n">i</span><span class="p">,</span> <span class="n">command</span><span class="o">=</span><span class="n">increment</span><span class="p">)</span>
|
||
<span class="n">button</span><span class="o">.</span><span class="n">pack</span><span class="p">()</span>
|
||
<span class="k">return</span> <span class="n">label</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However, this workaround only highlights the shortcomings of existing
|
||
scopes: the purpose of a function is to encapsulate code in its own
|
||
namespace, so it seems unfortunate that the programmer should have to
|
||
create additional namespaces to make up for missing functionality in
|
||
the existing local scopes, and then have to decide whether each name
|
||
should reside in the real scope or the simulated scope.</p>
|
||
<p>Another common objection is that the desired functionality can be
|
||
written as a class instead, albeit somewhat more verbosely. One
|
||
rebuttal to this objection is that the existence of a different
|
||
implementation style is not a reason to leave a supported programming
|
||
construct (nested scopes) functionally incomplete. Python is
|
||
sometimes called a “multi-paradigm language” because it derives so
|
||
much strength, practical flexibility, and pedagogical power from its
|
||
support and graceful integration of multiple programming paradigms.</p>
|
||
<p>A proposal for scoping syntax appeared on Python-Dev as far back as
|
||
1994 <a class="footnote-reference brackets" href="#id45" id="id1">[1]</a>, long before <a class="pep reference internal" href="../pep-0227/" title="PEP 227 – Statically Nested Scopes">PEP 227</a>’s support for nested scopes was
|
||
adopted. At the time, Guido’s response was:</p>
|
||
<blockquote>
|
||
<div>This is dangerously close to introducing CSNS [classic static
|
||
nested scopes]. <em>If</em> you were to do so, your proposed semantics
|
||
of scoped seem alright. I still think there is not enough need
|
||
for CSNS to warrant this kind of construct …</div></blockquote>
|
||
<p>After <a class="pep reference internal" href="../pep-0227/" title="PEP 227 – Statically Nested Scopes">PEP 227</a>, the “outer name rebinding discussion” has reappeared
|
||
on Python-Dev enough times that it has become a familiar event,
|
||
having recurred in its present form since at least 2003 <a class="footnote-reference brackets" href="#id46" id="id2">[2]</a>.
|
||
Although none of the language changes proposed in these discussions
|
||
have yet been adopted, Guido has acknowledged that a language change
|
||
is worth considering <a class="footnote-reference brackets" href="#id56" id="id3">[12]</a>.</p>
|
||
</section>
|
||
<section id="other-languages">
|
||
<h2><a class="toc-backref" href="#other-languages" role="doc-backlink">Other Languages</a></h2>
|
||
<p>To provide some background, this section describes how some other
|
||
languages handle nested scopes and rebinding.</p>
|
||
<section id="javascript-perl-scheme-smalltalk-gnu-c-c-2-0">
|
||
<h3><a class="toc-backref" href="#javascript-perl-scheme-smalltalk-gnu-c-c-2-0" role="doc-backlink">JavaScript, Perl, Scheme, Smalltalk, GNU C, C# 2.0</a></h3>
|
||
<p>These languages use variable declarations to indicate scope. In
|
||
JavaScript, a lexically scoped variable is declared with the <code class="docutils literal notranslate"><span class="pre">var</span></code>
|
||
keyword; undeclared variable names are assumed to be global. In
|
||
Perl, a lexically scoped variable is declared with the <code class="docutils literal notranslate"><span class="pre">my</span></code>
|
||
keyword; undeclared variable names are assumed to be global. In
|
||
Scheme, all variables must be declared (with <code class="docutils literal notranslate"><span class="pre">define</span></code> or <code class="docutils literal notranslate"><span class="pre">let</span></code>,
|
||
or as formal parameters). In Smalltalk, any block can begin by
|
||
declaring a list of local variable names between vertical bars.
|
||
C and C# require type declarations for all variables. For all these
|
||
cases, the variable belongs to the scope containing the declaration.</p>
|
||
</section>
|
||
<section id="ruby-as-of-1-8">
|
||
<h3><a class="toc-backref" href="#ruby-as-of-1-8" role="doc-backlink">Ruby (as of 1.8)</a></h3>
|
||
<p>Ruby is an instructive example because it appears to be the only
|
||
other currently popular language that, like Python, tries to support
|
||
statically nested scopes without requiring variable declarations, and
|
||
thus has to come up with an unusual solution. Functions in Ruby can
|
||
contain other function definitions, and they can also contain code
|
||
blocks enclosed in curly braces. Blocks have access to outer
|
||
variables, but nested functions do not. Within a block, an
|
||
assignment to a name implies a declaration of a local variable only
|
||
if it would not shadow a name already bound in an outer scope;
|
||
otherwise assignment is interpreted as rebinding of the outer name.
|
||
Ruby’s scoping syntax and rules have also been debated at great
|
||
length, and changes seem likely in Ruby 2.0 <a class="footnote-reference brackets" href="#id71" id="id4">[28]</a>.</p>
|
||
</section>
|
||
</section>
|
||
<section id="overview-of-proposals">
|
||
<h2><a class="toc-backref" href="#overview-of-proposals" role="doc-backlink">Overview of Proposals</a></h2>
|
||
<p>There have been many different proposals on Python-Dev for ways to
|
||
rebind names in outer scopes. They all fall into two categories:
|
||
new syntax in the scope where the name is bound, or new syntax in
|
||
the scope where the name is used.</p>
|
||
<section id="new-syntax-in-the-binding-outer-scope">
|
||
<h3><a class="toc-backref" href="#new-syntax-in-the-binding-outer-scope" role="doc-backlink">New Syntax in the Binding (Outer) Scope</a></h3>
|
||
<section id="scope-override-declaration">
|
||
<h4><a class="toc-backref" href="#scope-override-declaration" role="doc-backlink">Scope Override Declaration</a></h4>
|
||
<p>The proposals in this category all suggest a new kind of declaration
|
||
statement similar to JavaScript’s <code class="docutils literal notranslate"><span class="pre">var</span></code>. A few possible keywords
|
||
have been proposed for this purpose:</p>
|
||
<ul class="simple">
|
||
<li><code class="docutils literal notranslate"><span class="pre">scope</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id48" id="id5">[4]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">var</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id48" id="id6">[4]</a> <a class="footnote-reference brackets" href="#id53" id="id7">[9]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">my</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id57" id="id8">[13]</a></li>
|
||
</ul>
|
||
<p>In all these proposals, a declaration such as <code class="docutils literal notranslate"><span class="pre">var</span> <span class="pre">x</span></code> in a
|
||
particular scope S would cause all references to <code class="docutils literal notranslate"><span class="pre">x</span></code> in scopes
|
||
nested within S to refer to the <code class="docutils literal notranslate"><span class="pre">x</span></code> bound in S.</p>
|
||
<p>The primary objection to this category of proposals is that the
|
||
meaning of a function definition would become context-sensitive.
|
||
Moving a function definition inside some other block could cause any
|
||
of the local name references in the function to become nonlocal, due
|
||
to declarations in the enclosing block. For blocks in Ruby 1.8,
|
||
this is actually the case; in the following example, the two setters
|
||
have different effects even though they look identical:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">setter1</span> <span class="o">=</span> <span class="n">proc</span> <span class="p">{</span> <span class="o">|</span> <span class="n">x</span> <span class="o">|</span> <span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="p">}</span> <span class="c1"># y is local here</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="mi">13</span>
|
||
<span class="n">setter2</span> <span class="o">=</span> <span class="n">proc</span> <span class="p">{</span> <span class="o">|</span> <span class="n">x</span> <span class="o">|</span> <span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="p">}</span> <span class="c1"># y is nonlocal here</span>
|
||
<span class="n">setter1</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="mi">99</span><span class="p">)</span>
|
||
<span class="n">puts</span> <span class="n">y</span> <span class="c1"># prints 13</span>
|
||
<span class="n">setter2</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="mi">77</span><span class="p">)</span>
|
||
<span class="n">puts</span> <span class="n">y</span> <span class="c1"># prints 77</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that although this proposal resembles declarations in JavaScript
|
||
and Perl, the effect on the language is different because in those
|
||
languages undeclared variables are global by default, whereas in
|
||
Python undeclared variables are local by default. Thus, moving
|
||
a function inside some other block in JavaScript or Perl can only
|
||
reduce the scope of a previously global name reference, whereas in
|
||
Python with this proposal, it could expand the scope of a previously
|
||
local name reference.</p>
|
||
</section>
|
||
<section id="required-variable-declaration">
|
||
<h4><a class="toc-backref" href="#required-variable-declaration" role="doc-backlink">Required Variable Declaration</a></h4>
|
||
<p>A more radical proposal <a class="footnote-reference brackets" href="#id64" id="id9">[21]</a> suggests removing Python’s scope-guessing
|
||
convention altogether and requiring that all names be declared in the
|
||
scope where they are to be bound, much like Scheme. With this
|
||
proposal, <code class="docutils literal notranslate"><span class="pre">var</span> <span class="pre">x</span> <span class="pre">=</span> <span class="pre">3</span></code> would both declare <code class="docutils literal notranslate"><span class="pre">x</span></code> to belong to the
|
||
local scope and bind it, where as <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">3</span></code> would rebind the existing
|
||
visible <code class="docutils literal notranslate"><span class="pre">x</span></code>. In a context without an enclosing scope containing a
|
||
<code class="docutils literal notranslate"><span class="pre">var</span> <span class="pre">x</span></code> declaration, the statement <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">3</span></code> would be statically
|
||
determined to be illegal.</p>
|
||
<p>This proposal yields a simple and consistent model, but it would be
|
||
incompatible with all existing Python code.</p>
|
||
</section>
|
||
</section>
|
||
<section id="new-syntax-in-the-referring-inner-scope">
|
||
<h3><a class="toc-backref" href="#new-syntax-in-the-referring-inner-scope" role="doc-backlink">New Syntax in the Referring (Inner) Scope</a></h3>
|
||
<p>There are three kinds of proposals in this category.</p>
|
||
<section id="outer-reference-expression">
|
||
<h4><a class="toc-backref" href="#outer-reference-expression" role="doc-backlink">Outer Reference Expression</a></h4>
|
||
<p>This type of proposal suggests a new way of referring to a variable
|
||
in an outer scope when using the variable in an expression. One
|
||
syntax that has been suggested for this is <code class="docutils literal notranslate"><span class="pre">.x</span></code> <a class="footnote-reference brackets" href="#id51" id="id10">[7]</a>, which would
|
||
refer to <code class="docutils literal notranslate"><span class="pre">x</span></code> without creating a local binding for it. A concern
|
||
with this proposal is that in many contexts <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">.x</span></code> could
|
||
be used interchangeably, which would confuse the reader <a class="footnote-reference brackets" href="#id74" id="id11">[31]</a>. A
|
||
closely related idea is to use multiple dots to specify the number
|
||
of scope levels to ascend <a class="footnote-reference brackets" href="#id52" id="id12">[8]</a>, but most consider this too error-prone
|
||
<a class="footnote-reference brackets" href="#id60" id="id13">[17]</a>.</p>
|
||
</section>
|
||
<section id="rebinding-operator">
|
||
<h4><a class="toc-backref" href="#rebinding-operator" role="doc-backlink">Rebinding Operator</a></h4>
|
||
<p>This proposal suggests a new assignment-like operator that rebinds
|
||
a name without declaring the name to be local <a class="footnote-reference brackets" href="#id46" id="id14">[2]</a>. Whereas the
|
||
statement <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">3</span></code> both declares <code class="docutils literal notranslate"><span class="pre">x</span></code> a local variable and binds
|
||
it to 3, the statement <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">:=</span> <span class="pre">3</span></code> would change the existing binding
|
||
of <code class="docutils literal notranslate"><span class="pre">x</span></code> without declaring it local.</p>
|
||
<p>This is a simple solution, but according to <a class="pep reference internal" href="../pep-3099/" title="PEP 3099 – Things that will Not Change in Python 3000">PEP 3099</a> it has been
|
||
rejected (perhaps because it would be too easy to miss or to confuse
|
||
with <code class="docutils literal notranslate"><span class="pre">=</span></code>).</p>
|
||
</section>
|
||
<section id="id15">
|
||
<h4><a class="toc-backref" href="#id15" role="doc-backlink">Scope Override Declaration</a></h4>
|
||
<p>The proposals in this category suggest a new kind of declaration
|
||
statement in the inner scope that prevents a name from becoming
|
||
local. This statement would be similar in nature to the <code class="docutils literal notranslate"><span class="pre">global</span></code>
|
||
statement, but instead of making the name refer to a binding in the
|
||
top module-level scope, it would make the name refer to the binding
|
||
in the nearest enclosing scope.</p>
|
||
<p>This approach is attractive due to its parallel with a familiar
|
||
Python construct, and because it retains context-independence for
|
||
function definitions.</p>
|
||
<p>This approach also has advantages from a security and debugging
|
||
perspective. The resulting Python would not only match the
|
||
functionality of other nested-scope languages but would do so with a
|
||
syntax that is arguably even better for defensive programming. In
|
||
most other languages, a declaration contracts the scope of an
|
||
existing name, so inadvertently omitting the declaration could yield
|
||
farther-reaching (i.e. more dangerous) effects than expected. In
|
||
Python with this proposal, the extra effort of adding the declaration
|
||
is aligned with the increased risk of non-local effects (i.e. the
|
||
path of least resistance is the safer path).</p>
|
||
<p>Many spellings have been suggested for such a declaration:</p>
|
||
<ul class="simple">
|
||
<li><code class="docutils literal notranslate"><span class="pre">scoped</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id45" id="id16">[1]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">global</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">f</span></code> <a class="footnote-reference brackets" href="#id47" id="id17">[3]</a> (explicitly specify which scope)</li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">free</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id49" id="id18">[5]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">outer</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id50" id="id19">[6]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">use</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id53" id="id20">[9]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">global</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id54" id="id21">[10]</a> (change the meaning of <code class="docutils literal notranslate"><span class="pre">global</span></code>)</li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">nonlocal</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id55" id="id22">[11]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">global</span> <span class="pre">x</span> <span class="pre">outer</span></code> <a class="footnote-reference brackets" href="#id61" id="id23">[18]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">global</span> <span class="pre">in</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id61" id="id24">[18]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">not</span> <span class="pre">global</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id61" id="id25">[18]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">extern</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id63" id="id26">[20]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">ref</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id65" id="id27">[22]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">refer</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id65" id="id28">[22]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">share</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id65" id="id29">[22]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">sharing</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id65" id="id30">[22]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">common</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id65" id="id31">[22]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">using</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id65" id="id32">[22]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">borrow</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id65" id="id33">[22]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">reuse</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id66" id="id34">[23]</a></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">scope</span> <span class="pre">f</span> <span class="pre">x</span></code> <a class="footnote-reference brackets" href="#id68" id="id35">[25]</a> (explicitly specify which scope)</li>
|
||
</ul>
|
||
<p>The most commonly discussed choices appear to be <code class="docutils literal notranslate"><span class="pre">outer</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">global</span></code>, and <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code>. <code class="docutils literal notranslate"><span class="pre">outer</span></code> is already used as both a
|
||
variable name and an attribute name in the standard library. The
|
||
word <code class="docutils literal notranslate"><span class="pre">global</span></code> has a conflicting meaning, because “global variable”
|
||
is generally understood to mean a variable with top-level scope <a class="footnote-reference brackets" href="#id70" id="id36">[27]</a>.
|
||
In C, the keyword <code class="docutils literal notranslate"><span class="pre">extern</span></code> means that a name refers to a variable
|
||
in a different compilation unit. While <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code> is a bit long
|
||
and less pleasant-sounding than some of the other options, it does
|
||
have precisely the correct meaning: it declares a name not local.</p>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
<section id="proposed-solution">
|
||
<h2><a class="toc-backref" href="#proposed-solution" role="doc-backlink">Proposed Solution</a></h2>
|
||
<p>The solution proposed by this PEP is to add a scope override
|
||
declaration in the referring (inner) scope. Guido has expressed a
|
||
preference for this category of solution on Python-Dev <a class="footnote-reference brackets" href="#id58" id="id37">[14]</a> and has
|
||
shown approval for <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code> as the keyword <a class="footnote-reference brackets" href="#id62" id="id38">[19]</a>.</p>
|
||
<p>The proposed declaration:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">nonlocal</span> <span class="n">x</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>prevents <code class="docutils literal notranslate"><span class="pre">x</span></code> from becoming a local name in the current scope. All
|
||
occurrences of <code class="docutils literal notranslate"><span class="pre">x</span></code> in the current scope will refer to the <code class="docutils literal notranslate"><span class="pre">x</span></code>
|
||
bound in an outer enclosing scope. As with <code class="docutils literal notranslate"><span class="pre">global</span></code>, multiple
|
||
names are permitted:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">nonlocal</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If there is no pre-existing binding in an enclosing scope, the
|
||
compiler raises a SyntaxError. (It may be a bit of a stretch to
|
||
call this a syntax error, but so far SyntaxError is used for all
|
||
compile-time errors, including, for example, __future__ import
|
||
with an unknown feature name.) Guido has said that this kind of
|
||
declaration in the absence of an outer binding should be considered
|
||
an error <a class="footnote-reference brackets" href="#id59" id="id39">[16]</a>.</p>
|
||
<p>If a <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code> declaration collides with the name of a formal
|
||
parameter in the local scope, the compiler raises a SyntaxError.</p>
|
||
<p>A shorthand form is also permitted, in which <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code> is
|
||
prepended to an assignment or augmented assignment:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">nonlocal</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">3</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The above has exactly the same meaning as <code class="docutils literal notranslate"><span class="pre">nonlocal</span> <span class="pre">x;</span> <span class="pre">x</span> <span class="pre">=</span> <span class="pre">3</span></code>.
|
||
(Guido supports a similar form of the <code class="docutils literal notranslate"><span class="pre">global</span></code> statement <a class="footnote-reference brackets" href="#id67" id="id40">[24]</a>.)</p>
|
||
<p>On the left side of the shorthand form, only identifiers are allowed,
|
||
not target expressions like <code class="docutils literal notranslate"><span class="pre">x[0]</span></code>. Otherwise, all forms of
|
||
assignment are allowed. The proposed grammar of the <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code>
|
||
statement is:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">nonlocal_stmt</span> <span class="p">:</span><span class="o">:=</span>
|
||
<span class="s2">"nonlocal"</span> <span class="n">identifier</span> <span class="p">(</span><span class="s2">","</span> <span class="n">identifier</span><span class="p">)</span><span class="o">*</span>
|
||
<span class="p">[</span><span class="s2">"="</span> <span class="p">(</span><span class="n">target_list</span> <span class="s2">"="</span><span class="p">)</span><span class="o">+</span> <span class="n">expression_list</span><span class="p">]</span>
|
||
<span class="o">|</span> <span class="s2">"nonlocal"</span> <span class="n">identifier</span> <span class="n">augop</span> <span class="n">expression_list</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The rationale for allowing all these forms of assignment is that it
|
||
simplifies understanding of the <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code> statement. Separating
|
||
the shorthand form into a declaration and an assignment is sufficient
|
||
to understand what it means and whether it is valid.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>The shorthand syntax was not added in the original implementation
|
||
of the PEP. Later discussions <a class="footnote-reference brackets" href="#id72" id="id41">[29]</a> <a class="footnote-reference brackets" href="#id73" id="id42">[30]</a> concluded this syntax
|
||
should not be implemented.</p>
|
||
</div>
|
||
</section>
|
||
<section id="backward-compatibility">
|
||
<h2><a class="toc-backref" href="#backward-compatibility" role="doc-backlink">Backward Compatibility</a></h2>
|
||
<p>This PEP targets Python 3000, as suggested by Guido <a class="footnote-reference brackets" href="#id62" id="id43">[19]</a>. However,
|
||
others have noted that some options considered in this PEP may be
|
||
small enough changes to be feasible in Python 2.x <a class="footnote-reference brackets" href="#id69" id="id44">[26]</a>, in which
|
||
case this PEP could possibly be moved to be a 2.x series PEP.</p>
|
||
<p>As a (very rough) measure of the impact of introducing a new keyword,
|
||
here is the number of times that some of the proposed keywords appear
|
||
as identifiers in the standard library, according to a scan of the
|
||
Python SVN repository on November 5, 2006:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">nonlocal</span> <span class="mi">0</span>
|
||
<span class="n">use</span> <span class="mi">2</span>
|
||
<span class="n">using</span> <span class="mi">3</span>
|
||
<span class="n">reuse</span> <span class="mi">4</span>
|
||
<span class="n">free</span> <span class="mi">8</span>
|
||
<span class="n">outer</span> <span class="mi">147</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">global</span></code> appears 214 times as an existing keyword. As a measure
|
||
of the impact of using <code class="docutils literal notranslate"><span class="pre">global</span></code> as the outer-scope keyword, there
|
||
are 18 files in the standard library that would break as a result
|
||
of such a change (because a function declares a variable <code class="docutils literal notranslate"><span class="pre">global</span></code>
|
||
before that variable has been introduced in the global scope):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cgi</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">dummy_thread</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">mhlib</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">mimetypes</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">idlelib</span><span class="o">/</span><span class="n">PyShell</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">idlelib</span><span class="o">/</span><span class="n">run</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">msilib</span><span class="o">/</span><span class="fm">__init__</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">inspect_fodder</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_compiler</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_decimal</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_descr</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_dummy_threading</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_fileinput</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_global</span><span class="o">.</span><span class="n">py</span> <span class="p">(</span><span class="ow">not</span> <span class="n">counted</span><span class="p">:</span> <span class="n">this</span> <span class="n">tests</span> <span class="n">the</span> <span class="n">keyword</span> <span class="n">itself</span><span class="p">)</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_grammar</span><span class="o">.</span><span class="n">py</span> <span class="p">(</span><span class="ow">not</span> <span class="n">counted</span><span class="p">:</span> <span class="n">this</span> <span class="n">tests</span> <span class="n">the</span> <span class="n">keyword</span> <span class="n">itself</span><span class="p">)</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_itertools</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_multifile</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_scope</span><span class="o">.</span><span class="n">py</span> <span class="p">(</span><span class="ow">not</span> <span class="n">counted</span><span class="p">:</span> <span class="n">this</span> <span class="n">tests</span> <span class="n">the</span> <span class="n">keyword</span> <span class="n">itself</span><span class="p">)</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_threaded_import</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_threadsignals</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span><span class="n">test_warnings</span><span class="o">.</span><span class="n">py</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="references">
|
||
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
||
<aside class="footnote-list brackets">
|
||
<aside class="footnote brackets" id="id45" role="doc-footnote">
|
||
<dt class="label" id="id45">[1]<em> (<a href='#id1'>1</a>, <a href='#id16'>2</a>) </em></dt>
|
||
<dd>Scoping (was Re: Lambda binding solved?) (Rafael Bracho)
|
||
<a class="reference external" href="https://legacy.python.org/search/hypermail/python-1994q1/0301.html">https://legacy.python.org/search/hypermail/python-1994q1/0301.html</a></aside>
|
||
<aside class="footnote brackets" id="id46" role="doc-footnote">
|
||
<dt class="label" id="id46">[2]<em> (<a href='#id2'>1</a>, <a href='#id14'>2</a>) </em></dt>
|
||
<dd>Extended Function syntax (Just van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-February/032764.html">https://mail.python.org/pipermail/python-dev/2003-February/032764.html</a></aside>
|
||
<aside class="footnote brackets" id="id47" role="doc-footnote">
|
||
<dt class="label" id="id47">[<a href="#id17">3</a>]</dt>
|
||
<dd>Closure semantics (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2003-October/039214.html">https://mail.python.org/pipermail/python-dev/2003-October/039214.html</a></aside>
|
||
<aside class="footnote brackets" id="id48" role="doc-footnote">
|
||
<dt class="label" id="id48">[4]<em> (<a href='#id5'>1</a>, <a href='#id6'>2</a>) </em></dt>
|
||
<dd>Better Control of Nested Lexical Scopes (Almann T. Goo)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-February/061568.html">https://mail.python.org/pipermail/python-dev/2006-February/061568.html</a></aside>
|
||
<aside class="footnote brackets" id="id49" role="doc-footnote">
|
||
<dt class="label" id="id49">[<a href="#id18">5</a>]</dt>
|
||
<dd>PEP for Better Control of Nested Lexical Scopes (Jeremy Hylton)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-February/061602.html">https://mail.python.org/pipermail/python-dev/2006-February/061602.html</a></aside>
|
||
<aside class="footnote brackets" id="id50" role="doc-footnote">
|
||
<dt class="label" id="id50">[<a href="#id19">6</a>]</dt>
|
||
<dd>PEP for Better Control of Nested Lexical Scopes (Almann T. Goo)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-February/061603.html">https://mail.python.org/pipermail/python-dev/2006-February/061603.html</a></aside>
|
||
<aside class="footnote brackets" id="id51" role="doc-footnote">
|
||
<dt class="label" id="id51">[<a href="#id10">7</a>]</dt>
|
||
<dd>Using and binding relative names (Phillip J. Eby)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-February/061636.html">https://mail.python.org/pipermail/python-dev/2006-February/061636.html</a></aside>
|
||
<aside class="footnote brackets" id="id52" role="doc-footnote">
|
||
<dt class="label" id="id52">[<a href="#id12">8</a>]</dt>
|
||
<dd>Using and binding relative names (Steven Bethard)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-February/061749.html">https://mail.python.org/pipermail/python-dev/2006-February/061749.html</a></aside>
|
||
<aside class="footnote brackets" id="id53" role="doc-footnote">
|
||
<dt class="label" id="id53">[9]<em> (<a href='#id7'>1</a>, <a href='#id20'>2</a>) </em></dt>
|
||
<dd>Lexical scoping in Python 3k (Ka-Ping Yee)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066862.html">https://mail.python.org/pipermail/python-dev/2006-July/066862.html</a></aside>
|
||
<aside class="footnote brackets" id="id54" role="doc-footnote">
|
||
<dt class="label" id="id54">[<a href="#id21">10</a>]</dt>
|
||
<dd>Lexical scoping in Python 3k (Greg Ewing)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066889.html">https://mail.python.org/pipermail/python-dev/2006-July/066889.html</a></aside>
|
||
<aside class="footnote brackets" id="id55" role="doc-footnote">
|
||
<dt class="label" id="id55">[<a href="#id22">11</a>]</dt>
|
||
<dd>Lexical scoping in Python 3k (Ka-Ping Yee)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066942.html">https://mail.python.org/pipermail/python-dev/2006-July/066942.html</a></aside>
|
||
<aside class="footnote brackets" id="id56" role="doc-footnote">
|
||
<dt class="label" id="id56">[<a href="#id3">12</a>]</dt>
|
||
<dd>Lexical scoping in Python 3k (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066950.html">https://mail.python.org/pipermail/python-dev/2006-July/066950.html</a></aside>
|
||
<aside class="footnote brackets" id="id57" role="doc-footnote">
|
||
<dt class="label" id="id57">[<a href="#id8">13</a>]</dt>
|
||
<dd>Explicit Lexical Scoping (pre-PEP?) (Talin)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066978.html">https://mail.python.org/pipermail/python-dev/2006-July/066978.html</a></aside>
|
||
<aside class="footnote brackets" id="id58" role="doc-footnote">
|
||
<dt class="label" id="id58">[<a href="#id37">14</a>]</dt>
|
||
<dd>Explicit Lexical Scoping (pre-PEP?) (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066991.html">https://mail.python.org/pipermail/python-dev/2006-July/066991.html</a></aside>
|
||
</aside>
|
||
<p>[15] Explicit Lexical Scoping (pre-PEP?) (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066995.html">https://mail.python.org/pipermail/python-dev/2006-July/066995.html</a></p>
|
||
<aside class="footnote-list brackets">
|
||
<aside class="footnote brackets" id="id59" role="doc-footnote">
|
||
<dt class="label" id="id59">[<a href="#id39">16</a>]</dt>
|
||
<dd>Lexical scoping in Python 3k (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/066968.html">https://mail.python.org/pipermail/python-dev/2006-July/066968.html</a></aside>
|
||
<aside class="footnote brackets" id="id60" role="doc-footnote">
|
||
<dt class="label" id="id60">[<a href="#id13">17</a>]</dt>
|
||
<dd>Explicit Lexical Scoping (pre-PEP?) (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/067004.html">https://mail.python.org/pipermail/python-dev/2006-July/067004.html</a></aside>
|
||
<aside class="footnote brackets" id="id61" role="doc-footnote">
|
||
<dt class="label" id="id61">[18]<em> (<a href='#id23'>1</a>, <a href='#id24'>2</a>, <a href='#id25'>3</a>) </em></dt>
|
||
<dd>Explicit Lexical Scoping (pre-PEP?) (Andrew Clover)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/067007.html">https://mail.python.org/pipermail/python-dev/2006-July/067007.html</a></aside>
|
||
<aside class="footnote brackets" id="id62" role="doc-footnote">
|
||
<dt class="label" id="id62">[19]<em> (<a href='#id38'>1</a>, <a href='#id43'>2</a>) </em></dt>
|
||
<dd>Explicit Lexical Scoping (pre-PEP?) (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/067067.html">https://mail.python.org/pipermail/python-dev/2006-July/067067.html</a></aside>
|
||
<aside class="footnote brackets" id="id63" role="doc-footnote">
|
||
<dt class="label" id="id63">[<a href="#id26">20</a>]</dt>
|
||
<dd>Explicit Lexical Scoping (pre-PEP?) (Matthew Barnes)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-July/067221.html">https://mail.python.org/pipermail/python-dev/2006-July/067221.html</a></aside>
|
||
<aside class="footnote brackets" id="id64" role="doc-footnote">
|
||
<dt class="label" id="id64">[<a href="#id9">21</a>]</dt>
|
||
<dd>Sky pie: a “var” keyword (a thread started by Neil Toronto)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2006-October/003968.html">https://mail.python.org/pipermail/python-3000/2006-October/003968.html</a></aside>
|
||
<aside class="footnote brackets" id="id65" role="doc-footnote">
|
||
<dt class="label" id="id65">[22]<em> (<a href='#id27'>1</a>, <a href='#id28'>2</a>, <a href='#id29'>3</a>, <a href='#id30'>4</a>, <a href='#id31'>5</a>, <a href='#id32'>6</a>, <a href='#id33'>7</a>) </em></dt>
|
||
<dd>Alternatives to ‘outer’ (Talin)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2006-October/004021.html">https://mail.python.org/pipermail/python-3000/2006-October/004021.html</a></aside>
|
||
<aside class="footnote brackets" id="id66" role="doc-footnote">
|
||
<dt class="label" id="id66">[<a href="#id34">23</a>]</dt>
|
||
<dd>Alternatives to ‘outer’ (Jim Jewett)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2006-November/004153.html">https://mail.python.org/pipermail/python-3000/2006-November/004153.html</a></aside>
|
||
<aside class="footnote brackets" id="id67" role="doc-footnote">
|
||
<dt class="label" id="id67">[<a href="#id40">24</a>]</dt>
|
||
<dd>Draft PEP for outer scopes (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2006-November/004166.html">https://mail.python.org/pipermail/python-3000/2006-November/004166.html</a></aside>
|
||
<aside class="footnote brackets" id="id68" role="doc-footnote">
|
||
<dt class="label" id="id68">[<a href="#id35">25</a>]</dt>
|
||
<dd>Draft PEP for outer scopes (Talin)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2006-November/004190.html">https://mail.python.org/pipermail/python-3000/2006-November/004190.html</a></aside>
|
||
<aside class="footnote brackets" id="id69" role="doc-footnote">
|
||
<dt class="label" id="id69">[<a href="#id44">26</a>]</dt>
|
||
<dd>Draft PEP for outer scopes (Alyssa Coghlan)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2006-November/004237.html">https://mail.python.org/pipermail/python-3000/2006-November/004237.html</a></aside>
|
||
<aside class="footnote brackets" id="id70" role="doc-footnote">
|
||
<dt class="label" id="id70">[<a href="#id36">27</a>]</dt>
|
||
<dd>Global variable (version 2006-11-01T01:23:16)
|
||
<a class="reference external" href="https://en.wikipedia.org/w/index.php?title=Global_variable&oldid=85001451">https://en.wikipedia.org/w/index.php?title=Global_variable&oldid=85001451</a></aside>
|
||
<aside class="footnote brackets" id="id71" role="doc-footnote">
|
||
<dt class="label" id="id71">[<a href="#id4">28</a>]</dt>
|
||
<dd>Ruby 2.0 block local variable
|
||
<a class="reference external" href="https://web.archive.org/web/20070105131417/http://redhanded.hobix.com/inspect/ruby20BlockLocalVariable.html">https://web.archive.org/web/20070105131417/http://redhanded.hobix.com/inspect/ruby20BlockLocalVariable.html</a></aside>
|
||
<aside class="footnote brackets" id="id72" role="doc-footnote">
|
||
<dt class="label" id="id72">[<a href="#id41">29</a>]</dt>
|
||
<dd>Issue 4199: combining assignment with global & nonlocal (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2013-June/127142.html">https://mail.python.org/pipermail/python-dev/2013-June/127142.html</a></aside>
|
||
<aside class="footnote brackets" id="id73" role="doc-footnote">
|
||
<dt class="label" id="id73">[<a href="#id42">30</a>]</dt>
|
||
<dd>Whatever happened to ‘nonlocal x = y’? (Guido van Rossum)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-January/151627.html">https://mail.python.org/pipermail/python-dev/2018-January/151627.html</a></aside>
|
||
<aside class="footnote brackets" id="id74" role="doc-footnote">
|
||
<dt class="label" id="id74">[<a href="#id11">31</a>]</dt>
|
||
<dd>Using and binding relative names (Almann T. Goo)
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-February/061761.html">https://mail.python.org/pipermail/python-dev/2006-February/061761.html</a></aside>
|
||
</aside>
|
||
</section>
|
||
<section id="acknowledgements">
|
||
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
|
||
<p>The ideas and proposals mentioned in this PEP are gleaned from
|
||
countless Python-Dev postings. Thanks to Jim Jewett, Mike Orr,
|
||
Jason Orendorff, and Christian Tanzer for suggesting specific
|
||
edits to this PEP.</p>
|
||
</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-3104.rst">https://github.com/python/peps/blob/main/peps/pep-3104.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3104.rst">2023-10-11 12:05:51 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#other-languages">Other Languages</a><ul>
|
||
<li><a class="reference internal" href="#javascript-perl-scheme-smalltalk-gnu-c-c-2-0">JavaScript, Perl, Scheme, Smalltalk, GNU C, C# 2.0</a></li>
|
||
<li><a class="reference internal" href="#ruby-as-of-1-8">Ruby (as of 1.8)</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#overview-of-proposals">Overview of Proposals</a><ul>
|
||
<li><a class="reference internal" href="#new-syntax-in-the-binding-outer-scope">New Syntax in the Binding (Outer) Scope</a><ul>
|
||
<li><a class="reference internal" href="#scope-override-declaration">Scope Override Declaration</a></li>
|
||
<li><a class="reference internal" href="#required-variable-declaration">Required Variable Declaration</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#new-syntax-in-the-referring-inner-scope">New Syntax in the Referring (Inner) Scope</a><ul>
|
||
<li><a class="reference internal" href="#outer-reference-expression">Outer Reference Expression</a></li>
|
||
<li><a class="reference internal" href="#rebinding-operator">Rebinding Operator</a></li>
|
||
<li><a class="reference internal" href="#id15">Scope Override Declaration</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#proposed-solution">Proposed Solution</a></li>
|
||
<li><a class="reference internal" href="#backward-compatibility">Backward Compatibility</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</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-3104.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> |