707 lines
62 KiB
HTML
707 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 359 – The “make” Statement | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0359/">
|
||
<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 359 – The “make” Statement | peps.python.org'>
|
||
<meta property="og:description" content="This PEP proposes a generalization of the class-declaration syntax, the make statement. The proposed syntax and semantics parallel the syntax for class definition, and so:">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0359/">
|
||
<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 proposes a generalization of the class-declaration syntax, the make statement. The proposed syntax and semantics parallel the syntax for class definition, and so:">
|
||
<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 359</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 359 – The “make” Statement</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Steven Bethard <steven.bethard at gmail.com></dd>
|
||
<dt class="field-even">Status<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</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">05-Apr-2006</dd>
|
||
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-odd">2.6</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even">05-Apr-2006, 06-Apr-2006, 13-Apr-2006</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="#withdrawal-notice">Withdrawal Notice</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
|
||
<li><a class="reference internal" href="#example-simple-namespaces">Example: simple namespaces</a></li>
|
||
<li><a class="reference internal" href="#example-gui-objects">Example: GUI objects</a></li>
|
||
<li><a class="reference internal" href="#example-custom-descriptors">Example: custom descriptors</a></li>
|
||
<li><a class="reference internal" href="#example-property-namespaces">Example: property namespaces</a></li>
|
||
<li><a class="reference internal" href="#example-interfaces">Example: interfaces</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
|
||
<li><a class="reference internal" href="#keyword">Keyword</a></li>
|
||
<li><a class="reference internal" href="#the-make-statement-as-an-alternate-constructor">The make-statement as an alternate constructor</a></li>
|
||
<li><a class="reference internal" href="#customizing-the-dict-in-which-the-block-is-executed">Customizing the dict in which the block is executed</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#optional-extensions">Optional Extensions</a><ul>
|
||
<li><a class="reference internal" href="#remove-the-make-keyword">Remove the make keyword</a></li>
|
||
<li><a class="reference internal" href="#removing-metaclass-in-python-3000">Removing __metaclass__ in Python 3000</a></li>
|
||
<li><a class="reference internal" href="#removing-class-statements-in-python-3000">Removing class statements in Python 3000</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This PEP proposes a generalization of the class-declaration syntax,
|
||
the <code class="docutils literal notranslate"><span class="pre">make</span></code> statement. The proposed syntax and semantics parallel
|
||
the syntax for class definition, and so:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="o"><</span><span class="nb">callable</span><span class="o">></span> <span class="o"><</span><span class="n">name</span><span class="o">></span> <span class="o"><</span><span class="nb">tuple</span><span class="o">></span><span class="p">:</span>
|
||
<span class="o"><</span><span class="n">block</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>is translated into the assignment:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">name</span><span class="o">></span> <span class="o">=</span> <span class="o"><</span><span class="nb">callable</span><span class="o">></span><span class="p">(</span><span class="s2">"<name>"</span><span class="p">,</span> <span class="o"><</span><span class="nb">tuple</span><span class="o">></span><span class="p">,</span> <span class="o"><</span><span class="n">namespace</span><span class="o">></span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>where <code class="docutils literal notranslate"><span class="pre"><namespace></span></code> is the dict created by executing <code class="docutils literal notranslate"><span class="pre"><block></span></code>.
|
||
This is mostly syntactic sugar for:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>class <name> <tuple>:
|
||
__metaclass__ = <callable>
|
||
<block>
|
||
</pre></div>
|
||
</div>
|
||
<p>and is intended to help more clearly express the intent of the
|
||
statement when something other than a class is being created. Of
|
||
course, other syntax for such a statement is possible, but it is hoped
|
||
that by keeping a strong parallel to the class statement, an
|
||
understanding of how classes and metaclasses work will translate into
|
||
an understanding of how the make-statement works as well.</p>
|
||
<p>The PEP is based on a suggestion <a class="footnote-reference brackets" href="#id11" id="id1">[1]</a> from Michele Simionato on the
|
||
python-dev list.</p>
|
||
</section>
|
||
<section id="withdrawal-notice">
|
||
<h2><a class="toc-backref" href="#withdrawal-notice" role="doc-backlink">Withdrawal Notice</a></h2>
|
||
<p>This PEP was withdrawn at Guido’s request <a class="footnote-reference brackets" href="#id12" id="id2">[2]</a>. Guido didn’t like it,
|
||
and in particular didn’t like how the property use-case puts the
|
||
instance methods of a property at a different level than other
|
||
instance methods and requires fixed names for the property functions.</p>
|
||
</section>
|
||
<section id="motivation">
|
||
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
||
<p>Class statements provide two nice facilities to Python:</p>
|
||
<ol class="arabic simple">
|
||
<li>They execute a block of statements and provide the resulting
|
||
bindings as a dict to the metaclass.</li>
|
||
<li>They encourage DRY (don’t repeat yourself) by allowing the class
|
||
being created to know the name it is being assigned.</li>
|
||
</ol>
|
||
<p>Thus in a simple class statement like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="s1">'bar'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>the metaclass (<code class="docutils literal notranslate"><span class="pre">type</span></code>) gets called with something like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">C</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="s1">'C'</span><span class="p">,</span> <span class="p">(</span><span class="nb">object</span><span class="p">,),</span> <span class="p">{</span><span class="s1">'x'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'foo'</span><span class="p">:</span><span class="o"><</span><span class="n">function</span> <span class="n">foo</span> <span class="n">at</span> <span class="o">...></span><span class="p">})</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The class statement is just syntactic sugar for the above assignment
|
||
statement, but clearly a very useful sort of syntactic sugar. It
|
||
avoids not only the repetition of <code class="docutils literal notranslate"><span class="pre">C</span></code>, but also simplifies the
|
||
creation of the dict by allowing it to be expressed as a series of
|
||
statements.</p>
|
||
<p>Historically, type instances (a.k.a. class objects) have been the
|
||
only objects blessed with this sort of syntactic support. The make
|
||
statement aims to extend this support to other sorts of objects where
|
||
such syntax would also be useful.</p>
|
||
<section id="example-simple-namespaces">
|
||
<h3><a class="toc-backref" href="#example-simple-namespaces" role="doc-backlink">Example: simple namespaces</a></h3>
|
||
<p>Let’s say I have some attributes in a module that I access like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mod</span><span class="o">.</span><span class="n">thematic_roletype</span>
|
||
<span class="n">mod</span><span class="o">.</span><span class="n">opinion_roletype</span>
|
||
|
||
<span class="n">mod</span><span class="o">.</span><span class="n">text_format</span>
|
||
<span class="n">mod</span><span class="o">.</span><span class="n">html_format</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>and since “Namespaces are one honking great idea”, I’d like to be able
|
||
to access these attributes instead as:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mod</span><span class="o">.</span><span class="n">roletypes</span><span class="o">.</span><span class="n">thematic</span>
|
||
<span class="n">mod</span><span class="o">.</span><span class="n">roletypes</span><span class="o">.</span><span class="n">opinion</span>
|
||
|
||
<span class="n">mod</span><span class="o">.</span><span class="n">format</span><span class="o">.</span><span class="n">text</span>
|
||
<span class="n">mod</span><span class="o">.</span><span class="n">format</span><span class="o">.</span><span class="n">html</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>I currently have two main options:</p>
|
||
<ol class="arabic simple">
|
||
<li>Turn the module into a package, turn <code class="docutils literal notranslate"><span class="pre">roletypes</span></code> and <code class="docutils literal notranslate"><span class="pre">format</span></code>
|
||
into submodules, and move the attributes to the submodules.</li>
|
||
<li>Create <code class="docutils literal notranslate"><span class="pre">roletypes</span></code> and <code class="docutils literal notranslate"><span class="pre">format</span></code> classes, and move the
|
||
attributes to the classes.</li>
|
||
</ol>
|
||
<p>The former is a fair chunk of refactoring work, and produces two tiny
|
||
modules without much content. The latter keeps the attributes local
|
||
to the module, but creates classes when there is no intention of ever
|
||
creating instances of those classes.</p>
|
||
<p>In situations like this, it would be nice to simply be able to declare
|
||
a “namespace” to hold the few attributes. With the new make
|
||
statement, I could introduce my new namespaces with something like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="n">namespace</span> <span class="n">roletypes</span><span class="p">:</span>
|
||
<span class="n">thematic</span> <span class="o">=</span> <span class="o">...</span>
|
||
<span class="n">opinion</span> <span class="o">=</span> <span class="o">...</span>
|
||
|
||
<span class="n">make</span> <span class="n">namespace</span> <span class="nb">format</span><span class="p">:</span>
|
||
<span class="n">text</span> <span class="o">=</span> <span class="o">...</span>
|
||
<span class="n">html</span> <span class="o">=</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>and keep my attributes local to the module without making classes that
|
||
are never intended to be instantiated. One definition of namespace
|
||
that would make this work is:</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="nb">object</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Given this definition, at the end of the make-statements above,
|
||
<code class="docutils literal notranslate"><span class="pre">roletypes</span></code> and <code class="docutils literal notranslate"><span class="pre">format</span></code> would be namespace instances.</p>
|
||
</section>
|
||
<section id="example-gui-objects">
|
||
<h3><a class="toc-backref" href="#example-gui-objects" role="doc-backlink">Example: GUI objects</a></h3>
|
||
<p>In GUI toolkits, objects like frames and panels are often associated
|
||
with attributes and functions. With the make-statement, code that
|
||
looks something like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">root</span> <span class="o">=</span> <span class="n">Tkinter</span><span class="o">.</span><span class="n">Tk</span><span class="p">()</span>
|
||
<span class="n">frame</span> <span class="o">=</span> <span class="n">Tkinter</span><span class="o">.</span><span class="n">Frame</span><span class="p">(</span><span class="n">root</span><span class="p">)</span>
|
||
<span class="n">frame</span><span class="o">.</span><span class="n">pack</span><span class="p">()</span>
|
||
<span class="k">def</span> <span class="nf">say_hi</span><span class="p">():</span>
|
||
<span class="nb">print</span> <span class="s2">"hi there, everyone!"</span>
|
||
<span class="n">hi_there</span> <span class="o">=</span> <span class="n">Tkinter</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="s2">"Hello"</span><span class="p">,</span> <span class="n">command</span><span class="o">=</span><span class="n">say_hi</span><span class="p">)</span>
|
||
<span class="n">hi_there</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">Tkinter</span><span class="o">.</span><span class="n">LEFT</span><span class="p">)</span>
|
||
<span class="n">root</span><span class="o">.</span><span class="n">mainloop</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>could be rewritten to group the Button’s function with its
|
||
declaration:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">root</span> <span class="o">=</span> <span class="n">Tkinter</span><span class="o">.</span><span class="n">Tk</span><span class="p">()</span>
|
||
<span class="n">frame</span> <span class="o">=</span> <span class="n">Tkinter</span><span class="o">.</span><span class="n">Frame</span><span class="p">(</span><span class="n">root</span><span class="p">)</span>
|
||
<span class="n">frame</span><span class="o">.</span><span class="n">pack</span><span class="p">()</span>
|
||
<span class="n">make</span> <span class="n">Tkinter</span><span class="o">.</span><span class="n">Button</span> <span class="n">hi_there</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="s2">"Hello"</span>
|
||
<span class="k">def</span> <span class="nf">command</span><span class="p">():</span>
|
||
<span class="nb">print</span> <span class="s2">"hi there, everyone!"</span>
|
||
<span class="n">hi_there</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">Tkinter</span><span class="o">.</span><span class="n">LEFT</span><span class="p">)</span>
|
||
<span class="n">root</span><span class="o">.</span><span class="n">mainloop</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="example-custom-descriptors">
|
||
<h3><a class="toc-backref" href="#example-custom-descriptors" role="doc-backlink">Example: custom descriptors</a></h3>
|
||
<p>Since descriptors are used to customize access to an attribute, it’s
|
||
often useful to know the name of that attribute. Current Python
|
||
doesn’t give an easy way to find this name and so a lot of custom
|
||
descriptors, like Ian Bicking’s setonce descriptor <a class="footnote-reference brackets" href="#id13" id="id3">[3]</a>, have to hack
|
||
around this somehow. With the make-statement, you could create a
|
||
<code class="docutils literal notranslate"><span class="pre">setonce</span></code> attribute like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
<span class="n">make</span> <span class="n">setonce</span> <span class="n">x</span><span class="p">:</span>
|
||
<span class="s2">"A's x attribute"</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>where the <code class="docutils literal notranslate"><span class="pre">setonce</span></code> descriptor would be defined like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">setonce</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="s1">'_setonce_attr_</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">name</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">'__doc__'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="bp">self</span>
|
||
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__set__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||
<span class="nb">setattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span><span class="s2">"Attribute already set"</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">set</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
||
<span class="nb">setattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__delete__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
|
||
<span class="nb">delattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that unlike the original implementation, the private attribute
|
||
name is stable since it uses the name of the descriptor, and therefore
|
||
instances of class A are pickleable.</p>
|
||
</section>
|
||
<section id="example-property-namespaces">
|
||
<h3><a class="toc-backref" href="#example-property-namespaces" role="doc-backlink">Example: property namespaces</a></h3>
|
||
<p>Python’s property type takes three function arguments and a docstring
|
||
argument which, though relevant only to the property, must be declared
|
||
before it and then passed as arguments to the property call, e.g.:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
<span class="k">def</span> <span class="nf">get_x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
<span class="k">def</span> <span class="nf">set_x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="n">get_x</span><span class="p">,</span> <span class="n">set_x</span><span class="p">,</span> <span class="s2">"the x of the frobulation"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This issue has been brought up before, and Guido <a class="footnote-reference brackets" href="#id14" id="id4">[4]</a> and others <a class="footnote-reference brackets" href="#id15" id="id5">[5]</a>
|
||
have briefly mused over alternate property syntaxes to make declaring
|
||
properties easier. With the make-statement, the following syntax
|
||
could be supported:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
<span class="n">make</span> <span class="n">block_property</span> <span class="n">x</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="sd">'''The x of the frobulation'''</span>
|
||
<span class="k">def</span> <span class="nf">fget</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
<span class="k">def</span> <span class="nf">fset</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>with the following definition of <code class="docutils literal notranslate"><span class="pre">block_property</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">block_property</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">block_dict</span><span class="p">):</span>
|
||
<span class="n">fget</span> <span class="o">=</span> <span class="n">block_dict</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">'fget'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||
<span class="n">fset</span> <span class="o">=</span> <span class="n">block_dict</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">'fset'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||
<span class="n">fdel</span> <span class="o">=</span> <span class="n">block_dict</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">'fdel'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||
<span class="n">doc</span> <span class="o">=</span> <span class="n">block_dict</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">'__doc__'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||
<span class="k">assert</span> <span class="ow">not</span> <span class="n">block_dict</span>
|
||
<span class="k">return</span> <span class="nb">property</span><span class="p">(</span><span class="n">fget</span><span class="p">,</span> <span class="n">fset</span><span class="p">,</span> <span class="n">fdel</span><span class="p">,</span> <span class="n">doc</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="example-interfaces">
|
||
<h3><a class="toc-backref" href="#example-interfaces" role="doc-backlink">Example: interfaces</a></h3>
|
||
<p>Guido <a class="footnote-reference brackets" href="#id16" id="id6">[6]</a> and others have occasionally suggested introducing
|
||
interfaces into python. Most suggestions have offered syntax along
|
||
the lines of:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">interface</span> <span class="n">IFoo</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="sd">"""Foo blah blah"""</span>
|
||
|
||
<span class="k">def</span> <span class="nf">fumble</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""docstring"""</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>but since there is currently no way in Python to declare an interface
|
||
in this manner, most implementations of Python interfaces use class
|
||
objects instead, e.g. Zope’s:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">IFoo</span><span class="p">(</span><span class="n">Interface</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Foo blah blah"""</span>
|
||
|
||
<span class="k">def</span> <span class="nf">fumble</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""docstring"""</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>With the new make-statement, these interfaces could instead be
|
||
declared as:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="n">Interface</span> <span class="n">IFoo</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="sd">"""Foo blah blah"""</span>
|
||
|
||
<span class="k">def</span> <span class="nf">fumble</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""docstring"""</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>which makes the intent (that this is an interface, not a class) much
|
||
clearer.</p>
|
||
</section>
|
||
</section>
|
||
<section id="specification">
|
||
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
|
||
<p>Python will translate a make-statement:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="o"><</span><span class="nb">callable</span><span class="o">></span> <span class="o"><</span><span class="n">name</span><span class="o">></span> <span class="o"><</span><span class="nb">tuple</span><span class="o">></span><span class="p">:</span>
|
||
<span class="o"><</span><span class="n">block</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>into the assignment:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">name</span><span class="o">></span> <span class="o">=</span> <span class="o"><</span><span class="nb">callable</span><span class="o">></span><span class="p">(</span><span class="s2">"<name>"</span><span class="p">,</span> <span class="o"><</span><span class="nb">tuple</span><span class="o">></span><span class="p">,</span> <span class="o"><</span><span class="n">namespace</span><span class="o">></span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>where <code class="docutils literal notranslate"><span class="pre"><namespace></span></code> is the dict created by executing <code class="docutils literal notranslate"><span class="pre"><block></span></code>.
|
||
The <code class="docutils literal notranslate"><span class="pre"><tuple></span></code> expression is optional; if not present, an empty tuple
|
||
will be assumed.</p>
|
||
<p>A patch is available implementing these semantics <a class="footnote-reference brackets" href="#id17" id="id7">[7]</a>.</p>
|
||
<p>The make-statement introduces a new keyword, <code class="docutils literal notranslate"><span class="pre">make</span></code>. Thus in Python
|
||
2.6, the make-statement will have to be enabled using <code class="docutils literal notranslate"><span class="pre">from</span>
|
||
<span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">make_statement</span></code>.</p>
|
||
</section>
|
||
<section id="open-issues">
|
||
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
|
||
<section id="keyword">
|
||
<h3><a class="toc-backref" href="#keyword" role="doc-backlink">Keyword</a></h3>
|
||
<p>Does the <code class="docutils literal notranslate"><span class="pre">make</span></code> keyword break too much code? Originally, the make
|
||
statement used the keyword <code class="docutils literal notranslate"><span class="pre">create</span></code> (a suggestion due to Alyssa
|
||
Coghlan). However, investigations into the standard library <a class="footnote-reference brackets" href="#id18" id="id8">[8]</a> and
|
||
Zope+Plone code <a class="footnote-reference brackets" href="#id19" id="id9">[9]</a> revealed that <code class="docutils literal notranslate"><span class="pre">create</span></code> would break a lot more
|
||
code, so <code class="docutils literal notranslate"><span class="pre">make</span></code> was adopted as the keyword instead. However, there
|
||
are still a few instances where <code class="docutils literal notranslate"><span class="pre">make</span></code> would break code. Is there a
|
||
better keyword for the statement?</p>
|
||
<p>Some possible keywords and their counts in the standard library (plus
|
||
some installed packages):</p>
|
||
<ul class="simple">
|
||
<li>make - 2 (both in tests)</li>
|
||
<li>create - 19 (including existing function in imaplib)</li>
|
||
<li>build - 83 (including existing class in distutils.command.build)</li>
|
||
<li>construct - 0</li>
|
||
<li>produce - 0</li>
|
||
</ul>
|
||
</section>
|
||
<section id="the-make-statement-as-an-alternate-constructor">
|
||
<h3><a class="toc-backref" href="#the-make-statement-as-an-alternate-constructor" role="doc-backlink">The make-statement as an alternate constructor</a></h3>
|
||
<p>Currently, there are not many functions which have the signature
|
||
<code class="docutils literal notranslate"><span class="pre">(name,</span> <span class="pre">args,</span> <span class="pre">kwargs)</span></code>. That means that something like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="nb">dict</span> <span class="n">params</span><span class="p">:</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="mi">2</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>is currently impossible because the dict constructor has a different
|
||
signature. Does this sort of thing need to be supported? One
|
||
suggestion, by Carl Banks, would be to add a <code class="docutils literal notranslate"><span class="pre">__make__</span></code> magic method
|
||
that if found would be called instead of <code class="docutils literal notranslate"><span class="pre">__call__</span></code>. For types,
|
||
the <code class="docutils literal notranslate"><span class="pre">__make__</span></code> method would be identical to <code class="docutils literal notranslate"><span class="pre">__call__</span></code> and thus
|
||
unnecessary, but dicts could support the make-statement by defining a
|
||
<code class="docutils literal notranslate"><span class="pre">__make__</span></code> method on the dict type that looks something like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">__make__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Of course, rather than adding another magic method, the dict type
|
||
could just grow a classmethod something like <code class="docutils literal notranslate"><span class="pre">dict.fromblock</span></code> that
|
||
could be used like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="nb">dict</span><span class="o">.</span><span class="n">fromblock</span> <span class="n">params</span><span class="p">:</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="mi">2</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>So the question is, will many types want to use the make-statement as
|
||
an alternate constructor? And if so, does that alternate constructor
|
||
need to have the same name as the original constructor?</p>
|
||
</section>
|
||
<section id="customizing-the-dict-in-which-the-block-is-executed">
|
||
<h3><a class="toc-backref" href="#customizing-the-dict-in-which-the-block-is-executed" role="doc-backlink">Customizing the dict in which the block is executed</a></h3>
|
||
<p>Should users of the make-statement be able to determine in which dict
|
||
object the code is executed? This would allow the make-statement to
|
||
be used in situations where a normal dict object would not suffice,
|
||
e.g. if order and repeated names must be allowed. Allowing this sort
|
||
of customization could allow XML to be written without repeating
|
||
element names, and with nesting of make-statements corresponding to
|
||
nesting of XML elements:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="n">Element</span> <span class="n">html</span><span class="p">:</span>
|
||
<span class="n">make</span> <span class="n">Element</span> <span class="n">body</span><span class="p">:</span>
|
||
<span class="n">text</span><span class="p">(</span><span class="s1">'before first h1'</span><span class="p">)</span>
|
||
<span class="n">make</span> <span class="n">Element</span> <span class="n">h1</span><span class="p">:</span>
|
||
<span class="n">attrib</span><span class="p">(</span><span class="n">style</span><span class="o">=</span><span class="s1">'first'</span><span class="p">)</span>
|
||
<span class="n">text</span><span class="p">(</span><span class="s1">'first h1'</span><span class="p">)</span>
|
||
<span class="n">tail</span><span class="p">(</span><span class="s1">'after first h1'</span><span class="p">)</span>
|
||
<span class="n">make</span> <span class="n">Element</span> <span class="n">h1</span><span class="p">:</span>
|
||
<span class="n">attrib</span><span class="p">(</span><span class="n">style</span><span class="o">=</span><span class="s1">'second'</span><span class="p">)</span>
|
||
<span class="n">text</span><span class="p">(</span><span class="s1">'second h1'</span><span class="p">)</span>
|
||
<span class="n">tail</span><span class="p">(</span><span class="s1">'after second h1'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If the make-statement tried to get the dict in which to execute its
|
||
block by calling the callable’s <code class="docutils literal notranslate"><span class="pre">__make_dict__</span></code> method, the
|
||
following code would allow the make-statement to be used as above:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Element</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
|
||
<span class="k">class</span> <span class="nc">__make_dict__</span><span class="p">(</span><span class="nb">dict</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</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">kwargs</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_super</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">Element</span><span class="o">.</span><span class="n">__make_dict__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_super</span><span class="o">.</span><span class="fm">__init__</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">kwargs</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">elements</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">tail</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">attrib</span> <span class="o">=</span> <span class="p">{}</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_super</span><span class="o">.</span><span class="fm">__getitem__</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">name</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'attrib'</span><span class="p">,</span> <span class="s1">'text'</span><span class="p">,</span> <span class="s1">'tail'</span><span class="p">]:</span>
|
||
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'set_</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="nb">globals</span><span class="p">()[</span><span class="n">name</span><span class="p">]</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_super</span><span class="o">.</span><span class="fm">__setitem__</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">elements</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">set_attrib</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">attrib</span> <span class="o">=</span> <span class="n">kwargs</span>
|
||
|
||
<span class="k">def</span> <span class="nf">set_text</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span>
|
||
|
||
<span class="k">def</span> <span class="nf">set_tail</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">tail</span> <span class="o">=</span> <span class="n">text</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">edict</span><span class="p">):</span>
|
||
<span class="n">get_element</span> <span class="o">=</span> <span class="n">etree</span><span class="o">.</span><span class="n">ElementTree</span><span class="o">.</span><span class="n">Element</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">get_element</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">attrib</span><span class="o">=</span><span class="n">edict</span><span class="o">.</span><span class="n">attrib</span><span class="p">)</span>
|
||
<span class="n">result</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">edict</span><span class="o">.</span><span class="n">text</span>
|
||
<span class="n">result</span><span class="o">.</span><span class="n">tail</span> <span class="o">=</span> <span class="n">edict</span><span class="o">.</span><span class="n">tail</span>
|
||
<span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">edict</span><span class="o">.</span><span class="n">elements</span><span class="p">:</span>
|
||
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">result</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note, however, that the code to support this is somewhat fragile –
|
||
it has to magically populate the namespace with <code class="docutils literal notranslate"><span class="pre">attrib</span></code>, <code class="docutils literal notranslate"><span class="pre">text</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">tail</span></code>, and it assumes that every name binding inside the make
|
||
statement body is creating an Element. As it stands, this code would
|
||
break with the introduction of a simple for-loop to any one of the
|
||
make-statement bodies, because the for-loop would bind a name to a
|
||
non-Element object. This could be worked around by adding some sort
|
||
of isinstance check or attribute examination, but this still results
|
||
in a somewhat fragile solution.</p>
|
||
<p>It has also been pointed out that the with-statement can provide
|
||
equivalent nesting with a much more explicit syntax:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">Element</span><span class="p">(</span><span class="s1">'html'</span><span class="p">)</span> <span class="k">as</span> <span class="n">html</span><span class="p">:</span>
|
||
<span class="k">with</span> <span class="n">Element</span><span class="p">(</span><span class="s1">'body'</span><span class="p">)</span> <span class="k">as</span> <span class="n">body</span><span class="p">:</span>
|
||
<span class="n">body</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'before first h1'</span>
|
||
<span class="k">with</span> <span class="n">Element</span><span class="p">(</span><span class="s1">'h1'</span><span class="p">,</span> <span class="n">style</span><span class="o">=</span><span class="s1">'first'</span><span class="p">)</span> <span class="k">as</span> <span class="n">h1</span><span class="p">:</span>
|
||
<span class="n">h1</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'first h1'</span>
|
||
<span class="n">h1</span><span class="o">.</span><span class="n">tail</span> <span class="o">=</span> <span class="s1">'after first h1'</span>
|
||
<span class="k">with</span> <span class="n">Element</span><span class="p">(</span><span class="s1">'h1'</span><span class="p">,</span> <span class="n">style</span><span class="o">=</span><span class="s1">'second'</span><span class="p">)</span> <span class="k">as</span> <span class="n">h1</span><span class="p">:</span>
|
||
<span class="n">h1</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'second h1'</span>
|
||
<span class="n">h1</span><span class="o">.</span><span class="n">tail</span> <span class="o">=</span> <span class="s1">'after second h1'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>And if the repetition of the element names here is too much of a DRY
|
||
violation, it is also possible to eliminate all as-clauses except for
|
||
the first by adding a few methods to Element. <a class="footnote-reference brackets" href="#id20" id="id10">[10]</a></p>
|
||
<p>So are there real use-cases for executing the block in a dict of a
|
||
different type? And if so, should the make-statement be extended to
|
||
support them?</p>
|
||
</section>
|
||
</section>
|
||
<section id="optional-extensions">
|
||
<h2><a class="toc-backref" href="#optional-extensions" role="doc-backlink">Optional Extensions</a></h2>
|
||
<section id="remove-the-make-keyword">
|
||
<h3><a class="toc-backref" href="#remove-the-make-keyword" role="doc-backlink">Remove the make keyword</a></h3>
|
||
<p>It might be possible to remove the make keyword so that such
|
||
statements would begin with the callable being called, e.g.:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">namespace</span> <span class="n">ns</span><span class="p">:</span>
|
||
<span class="n">badger</span> <span class="o">=</span> <span class="mi">42</span>
|
||
<span class="k">def</span> <span class="nf">spam</span><span class="p">():</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">interface</span> <span class="n">C</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However, almost all other Python statements begin with a keyword, and
|
||
removing the keyword would make it harder to look up this construct in
|
||
the documentation. Additionally, this would add some complexity in
|
||
the grammar and so far I (Steven Bethard) have not been able to
|
||
implement the feature without the keyword.</p>
|
||
</section>
|
||
<section id="removing-metaclass-in-python-3000">
|
||
<h3><a class="toc-backref" href="#removing-metaclass-in-python-3000" role="doc-backlink">Removing __metaclass__ in Python 3000</a></h3>
|
||
<p>As a side-effect of its generality, the make-statement mostly
|
||
eliminates the need for the <code class="docutils literal notranslate"><span class="pre">__metaclass__</span></code> attribute in class
|
||
objects. Thus in Python 3000, instead of:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>class <name> <bases-tuple>:
|
||
__metaclass__ = <metaclass>
|
||
<block>
|
||
</pre></div>
|
||
</div>
|
||
<p>metaclasses could be supported by using the metaclass as the callable
|
||
in a make-statement:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="o"><</span><span class="n">metaclass</span><span class="o">></span> <span class="o"><</span><span class="n">name</span><span class="o">></span> <span class="o"><</span><span class="n">bases</span><span class="o">-</span><span class="nb">tuple</span><span class="o">></span><span class="p">:</span>
|
||
<span class="o"><</span><span class="n">block</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Removing the <code class="docutils literal notranslate"><span class="pre">__metaclass__</span></code> hook would simplify the BUILD_CLASS
|
||
opcode a bit.</p>
|
||
</section>
|
||
<section id="removing-class-statements-in-python-3000">
|
||
<h3><a class="toc-backref" href="#removing-class-statements-in-python-3000" role="doc-backlink">Removing class statements in Python 3000</a></h3>
|
||
<p>In the most extreme application of make-statements, the class
|
||
statement itself could be deprecated in favor of <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">type</span></code>
|
||
statements.</p>
|
||
</section>
|
||
</section>
|
||
<section id="references">
|
||
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
||
<aside class="footnote-list brackets">
|
||
<aside class="footnote brackets" id="id11" role="doc-footnote">
|
||
<dt class="label" id="id11">[<a href="#id1">1</a>]</dt>
|
||
<dd>Michele Simionato’s original suggestion
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-October/057435.html">https://mail.python.org/pipermail/python-dev/2005-October/057435.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id12" role="doc-footnote">
|
||
<dt class="label" id="id12">[<a href="#id2">2</a>]</dt>
|
||
<dd>Guido requests withdrawal
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2006-April/000936.html">https://mail.python.org/pipermail/python-3000/2006-April/000936.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id13" role="doc-footnote">
|
||
<dt class="label" id="id13">[<a href="#id3">3</a>]</dt>
|
||
<dd>Ian Bicking’s setonce descriptor
|
||
(<a class="reference external" href="http://blog.ianbicking.org/easy-readonly-attributes.html">http://blog.ianbicking.org/easy-readonly-attributes.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id14" role="doc-footnote">
|
||
<dt class="label" id="id14">[<a href="#id4">4</a>]</dt>
|
||
<dd>Guido ponders property syntax
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-October/057404.html">https://mail.python.org/pipermail/python-dev/2005-October/057404.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id15" role="doc-footnote">
|
||
<dt class="label" id="id15">[<a href="#id5">5</a>]</dt>
|
||
<dd>Namespace-based property recipe
|
||
(<a class="reference external" href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442418">http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442418</a>)</aside>
|
||
<aside class="footnote brackets" id="id16" role="doc-footnote">
|
||
<dt class="label" id="id16">[<a href="#id6">6</a>]</dt>
|
||
<dd>Python interfaces
|
||
(<a class="reference external" href="http://www.artima.com/weblogs/viewpost.jsp?thread=86641">http://www.artima.com/weblogs/viewpost.jsp?thread=86641</a>)</aside>
|
||
<aside class="footnote brackets" id="id17" role="doc-footnote">
|
||
<dt class="label" id="id17">[<a href="#id7">7</a>]</dt>
|
||
<dd>Make Statement patch
|
||
(<a class="reference external" href="http://ucsu.colorado.edu/~bethard/py/make_statement.patch">http://ucsu.colorado.edu/~bethard/py/make_statement.patch</a>)</aside>
|
||
<aside class="footnote brackets" id="id18" role="doc-footnote">
|
||
<dt class="label" id="id18">[<a href="#id8">8</a>]</dt>
|
||
<dd>Instances of create in the stdlib
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-list/2006-April/335159.html">https://mail.python.org/pipermail/python-list/2006-April/335159.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id19" role="doc-footnote">
|
||
<dt class="label" id="id19">[<a href="#id9">9</a>]</dt>
|
||
<dd>Instances of create in Zope+Plone
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-list/2006-April/335284.html">https://mail.python.org/pipermail/python-list/2006-April/335284.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id20" role="doc-footnote">
|
||
<dt class="label" id="id20">[<a href="#id10">10</a>]</dt>
|
||
<dd>Eliminate as-clauses in with-statement XML
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-list/2006-April/336774.html">https://mail.python.org/pipermail/python-list/2006-April/336774.html</a>)</aside>
|
||
</aside>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document has been placed in the public domain.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0359.rst">https://github.com/python/peps/blob/main/peps/pep-0359.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0359.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="#withdrawal-notice">Withdrawal Notice</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
|
||
<li><a class="reference internal" href="#example-simple-namespaces">Example: simple namespaces</a></li>
|
||
<li><a class="reference internal" href="#example-gui-objects">Example: GUI objects</a></li>
|
||
<li><a class="reference internal" href="#example-custom-descriptors">Example: custom descriptors</a></li>
|
||
<li><a class="reference internal" href="#example-property-namespaces">Example: property namespaces</a></li>
|
||
<li><a class="reference internal" href="#example-interfaces">Example: interfaces</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
|
||
<li><a class="reference internal" href="#keyword">Keyword</a></li>
|
||
<li><a class="reference internal" href="#the-make-statement-as-an-alternate-constructor">The make-statement as an alternate constructor</a></li>
|
||
<li><a class="reference internal" href="#customizing-the-dict-in-which-the-block-is-executed">Customizing the dict in which the block is executed</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#optional-extensions">Optional Extensions</a><ul>
|
||
<li><a class="reference internal" href="#remove-the-make-keyword">Remove the make keyword</a></li>
|
||
<li><a class="reference internal" href="#removing-metaclass-in-python-3000">Removing __metaclass__ in Python 3000</a></li>
|
||
<li><a class="reference internal" href="#removing-class-statements-in-python-3000">Removing class statements in Python 3000</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0359.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> |