750 lines
63 KiB
HTML
750 lines
63 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 435 – Adding an Enum type to the Python standard library | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0435/">
|
||
<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 435 – Adding an Enum type to the Python standard library | peps.python.org'>
|
||
<meta property="og:description" content="This PEP proposes adding an enumeration type to the Python standard library.">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0435/">
|
||
<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 adding an enumeration type to the Python standard library.">
|
||
<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 435</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 435 – Adding an Enum type to the Python standard library</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Barry Warsaw <barry at python.org>,
|
||
Eli Bendersky <eliben at gmail.com>,
|
||
Ethan Furman <ethan at stoneleaf.us></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">23-Feb-2013</dd>
|
||
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-odd">3.4</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even">23-Feb-2013, 02-May-2013</dd>
|
||
<dt class="field-odd">Replaces<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="../pep-0354/">354</a></dd>
|
||
<dt class="field-even">Resolution<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2013-May/126112.html">Python-Dev message</a></dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#status-of-discussions">Status of discussions</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
||
<li><a class="reference internal" href="#module-and-type-name">Module and type name</a></li>
|
||
<li><a class="reference internal" href="#proposed-semantics-for-the-new-enumeration-type">Proposed semantics for the new enumeration type</a><ul>
|
||
<li><a class="reference internal" href="#creating-an-enum">Creating an Enum</a></li>
|
||
<li><a class="reference internal" href="#programmatic-access-to-enumeration-members">Programmatic access to enumeration members</a></li>
|
||
<li><a class="reference internal" href="#duplicating-enum-members-and-values">Duplicating enum members and values</a></li>
|
||
<li><a class="reference internal" href="#comparisons">Comparisons</a></li>
|
||
<li><a class="reference internal" href="#allowed-members-and-attributes-of-enumerations">Allowed members and attributes of enumerations</a></li>
|
||
<li><a class="reference internal" href="#restricted-subclassing-of-enumerations">Restricted subclassing of enumerations</a></li>
|
||
<li><a class="reference internal" href="#intenum">IntEnum</a></li>
|
||
<li><a class="reference internal" href="#other-derived-enumerations">Other derived enumerations</a></li>
|
||
<li><a class="reference internal" href="#pickling">Pickling</a></li>
|
||
<li><a class="reference internal" href="#functional-api">Functional API</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#proposed-variations">Proposed variations</a><ul>
|
||
<li><a class="reference internal" href="#flufl-enum">flufl.enum</a></li>
|
||
<li><a class="reference internal" href="#not-having-to-specify-values-for-enums">Not having to specify values for enums</a></li>
|
||
<li><a class="reference internal" href="#using-special-names-or-forms-to-auto-assign-enum-values">Using special names or forms to auto-assign enum values</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#use-cases-in-the-standard-library">Use-cases in the standard library</a></li>
|
||
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This PEP proposes adding an enumeration type to the Python standard library.</p>
|
||
<p>An enumeration is a set of symbolic names bound to unique, constant values.
|
||
Within an enumeration, the values can be compared by identity, and the
|
||
enumeration itself can be iterated over.</p>
|
||
</section>
|
||
<section id="status-of-discussions">
|
||
<h2><a class="toc-backref" href="#status-of-discussions" role="doc-backlink">Status of discussions</a></h2>
|
||
<p>The idea of adding an enum type to Python is not new - <a class="pep reference internal" href="../pep-0354/" title="PEP 354 – Enumerations in Python">PEP 354</a> is a
|
||
previous attempt that was rejected in 2005. Recently a new set of discussions
|
||
was initiated <a class="footnote-reference brackets" href="#id11" id="id1">[3]</a> on the <code class="docutils literal notranslate"><span class="pre">python-ideas</span></code> mailing list. Many new ideas were
|
||
proposed in several threads; after a lengthy discussion Guido proposed adding
|
||
<code class="docutils literal notranslate"><span class="pre">flufl.enum</span></code> to the standard library <a class="footnote-reference brackets" href="#id12" id="id2">[4]</a>. During the PyCon 2013 language
|
||
summit the issue was discussed further. It became clear that many developers
|
||
want to see an enum that subclasses <code class="docutils literal notranslate"><span class="pre">int</span></code>, which can allow us to replace
|
||
many integer constants in the standard library by enums with friendly string
|
||
representations, without ceding backwards compatibility. An additional
|
||
discussion among several interested core developers led to the proposal of
|
||
having <code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> as a special case of <code class="docutils literal notranslate"><span class="pre">Enum</span></code>.</p>
|
||
<p>The key dividing issue between <code class="docutils literal notranslate"><span class="pre">Enum</span></code> and <code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> is whether comparing
|
||
to integers is semantically meaningful. For most uses of enumerations, it’s
|
||
a <strong>feature</strong> to reject comparison to integers; enums that compare to integers
|
||
lead, through transitivity, to comparisons between enums of unrelated types,
|
||
which isn’t desirable in most cases. For some uses, however, greater
|
||
interoperability with integers is desired. For instance, this is the case for
|
||
replacing existing standard library constants (such as <code class="docutils literal notranslate"><span class="pre">socket.AF_INET</span></code>)
|
||
with enumerations.</p>
|
||
<p>Further discussion in late April 2013 led to the conclusion that enumeration
|
||
members should belong to the type of their enum: <code class="docutils literal notranslate"><span class="pre">type(Color.red)</span> <span class="pre">==</span> <span class="pre">Color</span></code>.
|
||
Guido has pronounced a decision on this issue <a class="footnote-reference brackets" href="#id13" id="id3">[5]</a>, as well as related issues
|
||
of not allowing to subclass enums <a class="footnote-reference brackets" href="#id14" id="id4">[6]</a>, unless they define no enumeration
|
||
members <a class="footnote-reference brackets" href="#id15" id="id5">[7]</a>.</p>
|
||
<p>The PEP was accepted by Guido on May 10th, 2013 <a class="footnote-reference brackets" href="#id10" id="id6">[1]</a>.</p>
|
||
</section>
|
||
<section id="motivation">
|
||
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
||
<p><em>[Based partly on the Motivation stated in</em> <a class="pep reference internal" href="../pep-0354/" title="PEP 354 – Enumerations in Python">PEP 354</a><em>]</em></p>
|
||
<p>The properties of an enumeration are useful for defining an immutable, related
|
||
set of constant values that may or may not have a semantic meaning. Classic
|
||
examples are days of the week (Sunday through Saturday) and school assessment
|
||
grades (‘A’ through ‘D’, and ‘F’). Other examples include error status values
|
||
and states within a defined process.</p>
|
||
<p>It is possible to simply define a sequence of values of some other basic type,
|
||
such as <code class="docutils literal notranslate"><span class="pre">int</span></code> or <code class="docutils literal notranslate"><span class="pre">str</span></code>, to represent discrete arbitrary values. However,
|
||
an enumeration ensures that such values are distinct from any others including,
|
||
importantly, values within other enumerations, and that operations without
|
||
meaning (“Wednesday times two”) are not defined for these values. It also
|
||
provides a convenient printable representation of enum values without requiring
|
||
tedious repetition while defining them (i.e. no <code class="docutils literal notranslate"><span class="pre">GREEN</span> <span class="pre">=</span> <span class="pre">'green'</span></code>).</p>
|
||
</section>
|
||
<section id="module-and-type-name">
|
||
<h2><a class="toc-backref" href="#module-and-type-name" role="doc-backlink">Module and type name</a></h2>
|
||
<p>We propose to add a module named <code class="docutils literal notranslate"><span class="pre">enum</span></code> to the standard library. The main
|
||
type exposed by this module is <code class="docutils literal notranslate"><span class="pre">Enum</span></code>. Hence, to import the <code class="docutils literal notranslate"><span class="pre">Enum</span></code> type
|
||
user code will run:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="proposed-semantics-for-the-new-enumeration-type">
|
||
<h2><a class="toc-backref" href="#proposed-semantics-for-the-new-enumeration-type" role="doc-backlink">Proposed semantics for the new enumeration type</a></h2>
|
||
<section id="creating-an-enum">
|
||
<h3><a class="toc-backref" href="#creating-an-enum" role="doc-backlink">Creating an Enum</a></h3>
|
||
<p>Enumerations are created using the class syntax, which makes them easy to read
|
||
and write. An alternative creation method is described in <a class="reference internal" href="#functional-api">Functional API</a>.
|
||
To define an enumeration, subclass <code class="docutils literal notranslate"><span class="pre">Enum</span></code> as follows:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">Color</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">red</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">green</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">... </span> <span class="n">blue</span> <span class="o">=</span> <span class="mi">3</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><strong>A note on nomenclature</strong>: we call <code class="docutils literal notranslate"><span class="pre">Color</span></code> an <em>enumeration</em> (or <em>enum</em>)
|
||
and <code class="docutils literal notranslate"><span class="pre">Color.red</span></code>, <code class="docutils literal notranslate"><span class="pre">Color.green</span></code> are <em>enumeration members</em> (or
|
||
<em>enum members</em>). Enumeration members also have <em>values</em> (the value of
|
||
<code class="docutils literal notranslate"><span class="pre">Color.red</span></code> is <code class="docutils literal notranslate"><span class="pre">1</span></code>, etc.)</p>
|
||
<p>Enumeration members have human readable string representations:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">Color</span><span class="o">.</span><span class="n">red</span><span class="p">)</span>
|
||
<span class="go">Color.red</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>…while their <code class="docutils literal notranslate"><span class="pre">repr</span></code> has more information:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">Color</span><span class="o">.</span><span class="n">red</span><span class="p">))</span>
|
||
<span class="go"><Color.red: 1></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <em>type</em> of an enumeration member is the enumeration it belongs to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">type</span><span class="p">(</span><span class="n">Color</span><span class="o">.</span><span class="n">red</span><span class="p">)</span>
|
||
<span class="go"><Enum 'Color'></span>
|
||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">Color</span><span class="o">.</span><span class="n">green</span><span class="p">,</span> <span class="n">Color</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Enums also have a property that contains just their item name:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">Color</span><span class="o">.</span><span class="n">red</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
||
<span class="go">red</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Enumerations support iteration, in definition order:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Shake</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">vanilla</span> <span class="o">=</span> <span class="mi">7</span>
|
||
<span class="gp">... </span> <span class="n">chocolate</span> <span class="o">=</span> <span class="mi">4</span>
|
||
<span class="gp">... </span> <span class="n">cookies</span> <span class="o">=</span> <span class="mi">9</span>
|
||
<span class="gp">... </span> <span class="n">mint</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">for</span> <span class="n">shake</span> <span class="ow">in</span> <span class="n">Shake</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">shake</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">Shake.vanilla</span>
|
||
<span class="go">Shake.chocolate</span>
|
||
<span class="go">Shake.cookies</span>
|
||
<span class="go">Shake.mint</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Enumeration members are hashable, so they can be used in dictionaries and sets:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">apples</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="gp">>>> </span><span class="n">apples</span><span class="p">[</span><span class="n">Color</span><span class="o">.</span><span class="n">red</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'red delicious'</span>
|
||
<span class="gp">>>> </span><span class="n">apples</span><span class="p">[</span><span class="n">Color</span><span class="o">.</span><span class="n">green</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'granny smith'</span>
|
||
<span class="gp">>>> </span><span class="n">apples</span>
|
||
<span class="go">{<Color.red: 1>: 'red delicious', <Color.green: 2>: 'granny smith'}</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="programmatic-access-to-enumeration-members">
|
||
<h3><a class="toc-backref" href="#programmatic-access-to-enumeration-members" role="doc-backlink">Programmatic access to enumeration members</a></h3>
|
||
<p>Sometimes it’s useful to access members in enumerations programmatically (i.e.
|
||
situations where <code class="docutils literal notranslate"><span class="pre">Color.red</span></code> won’t do because the exact color is not known
|
||
at program-writing time). <code class="docutils literal notranslate"><span class="pre">Enum</span></code> allows such access:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Color</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="go"><Color.red: 1></span>
|
||
<span class="gp">>>> </span><span class="n">Color</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="go"><Color.blue: 3></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If you want to access enum members by <em>name</em>, use item access:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Color</span><span class="p">[</span><span class="s1">'red'</span><span class="p">]</span>
|
||
<span class="go"><Color.red: 1></span>
|
||
<span class="gp">>>> </span><span class="n">Color</span><span class="p">[</span><span class="s1">'green'</span><span class="p">]</span>
|
||
<span class="go"><Color.green: 2></span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="duplicating-enum-members-and-values">
|
||
<h3><a class="toc-backref" href="#duplicating-enum-members-and-values" role="doc-backlink">Duplicating enum members and values</a></h3>
|
||
<p>Having two enum members with the same name is invalid:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Shape</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">square</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">... </span> <span class="n">square</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">...</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">TypeError</span>: <span class="n">Attempted to reuse key: square</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However, two enum members are allowed to have the same value. Given two members
|
||
A and B with the same value (and A defined first), B is an alias to A. By-value
|
||
lookup of the value of A and B will return A. By-name lookup of B will also
|
||
return A:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Shape</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">square</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">... </span> <span class="n">diamond</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">circle</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">... </span> <span class="n">alias_for_square</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">Shape</span><span class="o">.</span><span class="n">square</span>
|
||
<span class="go"><Shape.square: 2></span>
|
||
<span class="gp">>>> </span><span class="n">Shape</span><span class="o">.</span><span class="n">alias_for_square</span>
|
||
<span class="go"><Shape.square: 2></span>
|
||
<span class="gp">>>> </span><span class="n">Shape</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||
<span class="go"><Shape.square: 2></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Iterating over the members of an enum does not provide the aliases:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">Shape</span><span class="p">)</span>
|
||
<span class="go">[<Shape.square: 2>, <Shape.diamond: 1>, <Shape.circle: 3>]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The special attribute <code class="docutils literal notranslate"><span class="pre">__members__</span></code> is an ordered dictionary mapping names
|
||
to members. It includes all names defined in the enumeration, including the
|
||
aliases:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">member</span> <span class="ow">in</span> <span class="n">Shape</span><span class="o">.</span><span class="n">__members__</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="n">name</span><span class="p">,</span> <span class="n">member</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">('square', <Shape.square: 2>)</span>
|
||
<span class="go">('diamond', <Shape.diamond: 1>)</span>
|
||
<span class="go">('circle', <Shape.circle: 3>)</span>
|
||
<span class="go">('alias_for_square', <Shape.square: 2>)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">__members__</span></code> attribute can be used for detailed programmatic access to
|
||
the enumeration members. For example, finding all the aliases:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="p">[</span><span class="n">name</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">member</span> <span class="ow">in</span> <span class="n">Shape</span><span class="o">.</span><span class="n">__members__</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">member</span><span class="o">.</span><span class="n">name</span> <span class="o">!=</span> <span class="n">name</span><span class="p">]</span>
|
||
<span class="go">['alias_for_square']</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="comparisons">
|
||
<h3><a class="toc-backref" href="#comparisons" role="doc-backlink">Comparisons</a></h3>
|
||
<p>Enumeration members are compared by identity:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">red</span> <span class="ow">is</span> <span class="n">Color</span><span class="o">.</span><span class="n">red</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">red</span> <span class="ow">is</span> <span class="n">Color</span><span class="o">.</span><span class="n">blue</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">red</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">Color</span><span class="o">.</span><span class="n">blue</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Ordered comparisons between enumeration values are <em>not</em> supported. Enums are
|
||
not integers (but see <a class="reference internal" href="#intenum">IntEnum</a> below):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">red</span> <span class="o"><</span> <span class="n">Color</span><span class="o">.</span><span class="n">blue</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">TypeError</span>: <span class="n">unorderable types: Color() < Color()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Equality comparisons are defined though:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">blue</span> <span class="o">==</span> <span class="n">Color</span><span class="o">.</span><span class="n">red</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">blue</span> <span class="o">!=</span> <span class="n">Color</span><span class="o">.</span><span class="n">red</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">blue</span> <span class="o">==</span> <span class="n">Color</span><span class="o">.</span><span class="n">blue</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Comparisons against non-enumeration values will always compare not equal
|
||
(again, <code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> was explicitly designed to behave differently, see
|
||
below):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Color</span><span class="o">.</span><span class="n">blue</span> <span class="o">==</span> <span class="mi">2</span>
|
||
<span class="go">False</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="allowed-members-and-attributes-of-enumerations">
|
||
<h3><a class="toc-backref" href="#allowed-members-and-attributes-of-enumerations" role="doc-backlink">Allowed members and attributes of enumerations</a></h3>
|
||
<p>The examples above use integers for enumeration values. Using integers is
|
||
short and handy (and provided by default by the <a class="reference internal" href="#functional-api">Functional API</a>), but not
|
||
strictly enforced. In the vast majority of use-cases, one doesn’t care what
|
||
the actual value of an enumeration is. But if the value <em>is</em> important,
|
||
enumerations can have arbitrary values.</p>
|
||
<p>Enumerations are Python classes, and can have methods and special methods as
|
||
usual. If we have this enumeration:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Mood</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="n">funky</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">happy</span> <span class="o">=</span> <span class="mi">3</span>
|
||
|
||
<span class="k">def</span> <span class="nf">describe</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># self is the member here</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="s1">'my custom str! </span><span class="si">{0}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
|
||
<span class="nd">@classmethod</span>
|
||
<span class="k">def</span> <span class="nf">favorite_mood</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
|
||
<span class="c1"># cls here is the enumeration</span>
|
||
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">happy</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Then:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Mood</span><span class="o">.</span><span class="n">favorite_mood</span><span class="p">()</span>
|
||
<span class="go"><Mood.happy: 3></span>
|
||
<span class="gp">>>> </span><span class="n">Mood</span><span class="o">.</span><span class="n">happy</span><span class="o">.</span><span class="n">describe</span><span class="p">()</span>
|
||
<span class="go">('happy', 3)</span>
|
||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">Mood</span><span class="o">.</span><span class="n">funky</span><span class="p">)</span>
|
||
<span class="go">'my custom str! 1'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The rules for what is allowed are as follows: all attributes defined within an
|
||
enumeration will become members of this enumeration, with the exception of
|
||
<em>__dunder__</em> names and descriptors <a class="footnote-reference brackets" href="#id18" id="id7">[9]</a>; methods are descriptors too.</p>
|
||
</section>
|
||
<section id="restricted-subclassing-of-enumerations">
|
||
<h3><a class="toc-backref" href="#restricted-subclassing-of-enumerations" role="doc-backlink">Restricted subclassing of enumerations</a></h3>
|
||
<p>Subclassing an enumeration is allowed only if the enumeration does not define
|
||
any members. So this is forbidden:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">MoreColor</span><span class="p">(</span><span class="n">Color</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">pink</span> <span class="o">=</span> <span class="mi">17</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">TypeError: Cannot extend enumerations</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>But this is allowed:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Foo</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">some_behavior</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">Bar</span><span class="p">(</span><span class="n">Foo</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">happy</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">sad</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The rationale for this decision was given by Guido in <a class="footnote-reference brackets" href="#id14" id="id8">[6]</a>. Allowing to
|
||
subclass enums that define members would lead to a violation of some
|
||
important invariants of types and instances. On the other hand, it
|
||
makes sense to allow sharing some common behavior between a group of
|
||
enumerations, and subclassing empty enumerations is also used to implement
|
||
<code class="docutils literal notranslate"><span class="pre">IntEnum</span></code>.</p>
|
||
</section>
|
||
<section id="intenum">
|
||
<h3><a class="toc-backref" href="#intenum" role="doc-backlink">IntEnum</a></h3>
|
||
<p>A variation of <code class="docutils literal notranslate"><span class="pre">Enum</span></code> is proposed which is also a subclass of <code class="docutils literal notranslate"><span class="pre">int</span></code>.
|
||
Members of an <code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> can be compared to integers; by extension,
|
||
integer enumerations of different types can also be compared to each other:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">IntEnum</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">Shape</span><span class="p">(</span><span class="n">IntEnum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">circle</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">square</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">Request</span><span class="p">(</span><span class="n">IntEnum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">post</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">get</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">Shape</span> <span class="o">==</span> <span class="mi">1</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="n">Shape</span><span class="o">.</span><span class="n">circle</span> <span class="o">==</span> <span class="mi">1</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">Shape</span><span class="o">.</span><span class="n">circle</span> <span class="o">==</span> <span class="n">Request</span><span class="o">.</span><span class="n">post</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However they still can’t be compared to <code class="docutils literal notranslate"><span class="pre">Enum</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Shape</span><span class="p">(</span><span class="n">IntEnum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">circle</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">square</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">Color</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">red</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">green</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">Shape</span><span class="o">.</span><span class="n">circle</span> <span class="o">==</span> <span class="n">Color</span><span class="o">.</span><span class="n">red</span>
|
||
<span class="go">False</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> values behave like integers in other ways you’d expect:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">int</span><span class="p">(</span><span class="n">Shape</span><span class="o">.</span><span class="n">circle</span><span class="p">)</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>> </span><span class="p">[</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'b'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">][</span><span class="n">Shape</span><span class="o">.</span><span class="n">circle</span><span class="p">]</span>
|
||
<span class="go">'b'</span>
|
||
<span class="gp">>>> </span><span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">Shape</span><span class="o">.</span><span class="n">square</span><span class="p">)]</span>
|
||
<span class="go">[0, 1]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>For the vast majority of code, <code class="docutils literal notranslate"><span class="pre">Enum</span></code> is strongly recommended,
|
||
since <code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> breaks some semantic promises of an enumeration (by
|
||
being comparable to integers, and thus by transitivity to other
|
||
unrelated enumerations). It should be used only in special cases where
|
||
there’s no other choice; for example, when integer constants are
|
||
replaced with enumerations and backwards compatibility is required
|
||
with code that still expects integers.</p>
|
||
</section>
|
||
<section id="other-derived-enumerations">
|
||
<h3><a class="toc-backref" href="#other-derived-enumerations" role="doc-backlink">Other derived enumerations</a></h3>
|
||
<p><code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> will be part of the <code class="docutils literal notranslate"><span class="pre">enum</span></code> module. However, it would be very
|
||
simple to implement independently:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">IntEnum</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">Enum</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This demonstrates how similar derived enumerations can be defined, for example
|
||
a <code class="docutils literal notranslate"><span class="pre">StrEnum</span></code> that mixes in <code class="docutils literal notranslate"><span class="pre">str</span></code> instead of <code class="docutils literal notranslate"><span class="pre">int</span></code>.</p>
|
||
<p>Some rules:</p>
|
||
<ol class="arabic simple">
|
||
<li>When subclassing Enum, mix-in types must appear before Enum itself in the
|
||
sequence of bases, as in the <code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> example above.</li>
|
||
<li>While Enum can have members of any type, once you mix in an additional
|
||
type, all the members must have values of that type, e.g. <code class="docutils literal notranslate"><span class="pre">int</span></code> above.
|
||
This restriction does not apply to mix-ins which only add methods
|
||
and don’t specify another data type such as <code class="docutils literal notranslate"><span class="pre">int</span></code> or <code class="docutils literal notranslate"><span class="pre">str</span></code>.</li>
|
||
</ol>
|
||
</section>
|
||
<section id="pickling">
|
||
<h3><a class="toc-backref" href="#pickling" role="doc-backlink">Pickling</a></h3>
|
||
<p>Enumerations can be pickled and unpickled:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">enum.tests.fruit</span> <span class="kn">import</span> <span class="n">Fruit</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">pickle</span> <span class="kn">import</span> <span class="n">dumps</span><span class="p">,</span> <span class="n">loads</span>
|
||
<span class="gp">>>> </span><span class="n">Fruit</span><span class="o">.</span><span class="n">tomato</span> <span class="ow">is</span> <span class="n">loads</span><span class="p">(</span><span class="n">dumps</span><span class="p">(</span><span class="n">Fruit</span><span class="o">.</span><span class="n">tomato</span><span class="p">))</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The usual restrictions for pickling apply: picklable enums must be defined in
|
||
the top level of a module, since unpickling requires them to be importable
|
||
from that module.</p>
|
||
</section>
|
||
<section id="functional-api">
|
||
<h3><a class="toc-backref" href="#functional-api" role="doc-backlink">Functional API</a></h3>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">Enum</span></code> class is callable, providing the following functional API:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Animal</span> <span class="o">=</span> <span class="n">Enum</span><span class="p">(</span><span class="s1">'Animal'</span><span class="p">,</span> <span class="s1">'ant bee cat dog'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">Animal</span>
|
||
<span class="go"><Enum 'Animal'></span>
|
||
<span class="gp">>>> </span><span class="n">Animal</span><span class="o">.</span><span class="n">ant</span>
|
||
<span class="go"><Animal.ant: 1></span>
|
||
<span class="gp">>>> </span><span class="n">Animal</span><span class="o">.</span><span class="n">ant</span><span class="o">.</span><span class="n">value</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">Animal</span><span class="p">)</span>
|
||
<span class="go">[<Animal.ant: 1>, <Animal.bee: 2>, <Animal.cat: 3>, <Animal.dog: 4>]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The semantics of this API resemble <code class="docutils literal notranslate"><span class="pre">namedtuple</span></code>. The first argument
|
||
of the call to <code class="docutils literal notranslate"><span class="pre">Enum</span></code> is the name of the enumeration. Pickling enums
|
||
created with the functional API will work on CPython and PyPy, but for
|
||
IronPython and Jython you may need to specify the module name explicitly
|
||
as follows:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Animals</span> <span class="o">=</span> <span class="n">Enum</span><span class="p">(</span><span class="s1">'Animals'</span><span class="p">,</span> <span class="s1">'ant bee cat dog'</span><span class="p">,</span> <span class="n">module</span><span class="o">=</span><span class="vm">__name__</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The second argument is the <em>source</em> of enumeration member names. It can be a
|
||
whitespace-separated string of names, a sequence of names, a sequence of
|
||
2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to
|
||
values. The last two options enable assigning arbitrary values to
|
||
enumerations; the others auto-assign increasing integers starting with 1. A
|
||
new class derived from <code class="docutils literal notranslate"><span class="pre">Enum</span></code> is returned. In other words, the above
|
||
assignment to <code class="docutils literal notranslate"><span class="pre">Animal</span></code> is equivalent to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Animals</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">ant</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">... </span> <span class="n">bee</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">... </span> <span class="n">cat</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">... </span> <span class="n">dog</span> <span class="o">=</span> <span class="mi">4</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The reason for defaulting to <code class="docutils literal notranslate"><span class="pre">1</span></code> as the starting number and not <code class="docutils literal notranslate"><span class="pre">0</span></code> is
|
||
that <code class="docutils literal notranslate"><span class="pre">0</span></code> is <code class="docutils literal notranslate"><span class="pre">False</span></code> in a boolean sense, but enum members all evaluate
|
||
to <code class="docutils literal notranslate"><span class="pre">True</span></code>.</p>
|
||
</section>
|
||
</section>
|
||
<section id="proposed-variations">
|
||
<h2><a class="toc-backref" href="#proposed-variations" role="doc-backlink">Proposed variations</a></h2>
|
||
<p>Some variations were proposed during the discussions in the mailing list.
|
||
Here’s some of the more popular ones.</p>
|
||
<section id="flufl-enum">
|
||
<h3><a class="toc-backref" href="#flufl-enum" role="doc-backlink">flufl.enum</a></h3>
|
||
<p><code class="docutils literal notranslate"><span class="pre">flufl.enum</span></code> was the reference implementation upon which this PEP was
|
||
originally based. Eventually, it was decided against the inclusion of
|
||
<code class="docutils literal notranslate"><span class="pre">flufl.enum</span></code> because its design separated enumeration members from
|
||
enumerations, so the former are not instances of the latter. Its design
|
||
also explicitly permits subclassing enumerations for extending them with
|
||
more members (due to the member/enum separation, the type invariants are not
|
||
violated in <code class="docutils literal notranslate"><span class="pre">flufl.enum</span></code> with such a scheme).</p>
|
||
</section>
|
||
<section id="not-having-to-specify-values-for-enums">
|
||
<h3><a class="toc-backref" href="#not-having-to-specify-values-for-enums" role="doc-backlink">Not having to specify values for enums</a></h3>
|
||
<p>Michael Foord proposed (and Tim Delaney provided a proof-of-concept
|
||
implementation) to use metaclass magic that makes this possible:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Color</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="n">red</span><span class="p">,</span> <span class="n">green</span><span class="p">,</span> <span class="n">blue</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The values get actually assigned only when first looked up.</p>
|
||
<p>Pros: cleaner syntax that requires less typing for a very common task (just
|
||
listing enumeration names without caring about the values).</p>
|
||
<p>Cons: involves much magic in the implementation, which makes even the
|
||
definition of such enums baffling when first seen. Besides, explicit is
|
||
better than implicit.</p>
|
||
</section>
|
||
<section id="using-special-names-or-forms-to-auto-assign-enum-values">
|
||
<h3><a class="toc-backref" href="#using-special-names-or-forms-to-auto-assign-enum-values" role="doc-backlink">Using special names or forms to auto-assign enum values</a></h3>
|
||
<p>A different approach to avoid specifying enum values is to use a special name
|
||
or form to auto assign them. For example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Color</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="n">red</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># auto-assigned to 0</span>
|
||
<span class="n">green</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># auto-assigned to 1</span>
|
||
<span class="n">blue</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># auto-assigned to 2</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>More flexibly:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Color</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="n">red</span> <span class="o">=</span> <span class="mi">7</span>
|
||
<span class="n">green</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># auto-assigned to 8</span>
|
||
<span class="n">blue</span> <span class="o">=</span> <span class="mi">19</span>
|
||
<span class="n">purple</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># auto-assigned to 20</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Some variations on this theme:</p>
|
||
<ol class="arabic simple">
|
||
<li>A special name <code class="docutils literal notranslate"><span class="pre">auto</span></code> imported from the enum package.</li>
|
||
<li>Georg Brandl proposed ellipsis (<code class="docutils literal notranslate"><span class="pre">...</span></code>) instead of <code class="docutils literal notranslate"><span class="pre">None</span></code> to achieve the
|
||
same effect.</li>
|
||
</ol>
|
||
<p>Pros: no need to manually enter values. Makes it easier to change the enum and
|
||
extend it, especially for large enumerations.</p>
|
||
<p>Cons: actually longer to type in many simple cases. The argument of explicit
|
||
vs. implicit applies here as well.</p>
|
||
</section>
|
||
</section>
|
||
<section id="use-cases-in-the-standard-library">
|
||
<h2><a class="toc-backref" href="#use-cases-in-the-standard-library" role="doc-backlink">Use-cases in the standard library</a></h2>
|
||
<p>The Python standard library has many places where the usage of enums would be
|
||
beneficial to replace other idioms currently used to represent them. Such
|
||
usages can be divided to two categories: user-code facing constants, and
|
||
internal constants.</p>
|
||
<p>User-code facing constants like <code class="docutils literal notranslate"><span class="pre">os.SEEK_*</span></code>, <code class="docutils literal notranslate"><span class="pre">socket</span></code> module constants,
|
||
decimal rounding modes and HTML error codes could require backwards
|
||
compatibility since user code may expect integers. <code class="docutils literal notranslate"><span class="pre">IntEnum</span></code> as described
|
||
above provides the required semantics; being a subclass of <code class="docutils literal notranslate"><span class="pre">int</span></code>, it does not
|
||
affect user code that expects integers, while on the other hand allowing
|
||
printable representations for enumeration values:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">socket</span>
|
||
<span class="gp">>>> </span><span class="n">family</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span>
|
||
<span class="gp">>>> </span><span class="n">family</span> <span class="o">==</span> <span class="mi">2</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">family</span><span class="p">)</span>
|
||
<span class="go">SocketFamily.AF_INET</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Internal constants are not seen by user code but are employed internally by
|
||
stdlib modules. These can be implemented with <code class="docutils literal notranslate"><span class="pre">Enum</span></code>. Some examples
|
||
uncovered by a very partial skim through the stdlib: <code class="docutils literal notranslate"><span class="pre">binhex</span></code>, <code class="docutils literal notranslate"><span class="pre">imaplib</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">http/client</span></code>, <code class="docutils literal notranslate"><span class="pre">urllib/robotparser</span></code>, <code class="docutils literal notranslate"><span class="pre">idlelib</span></code>, <code class="docutils literal notranslate"><span class="pre">concurrent.futures</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">turtledemo</span></code>.</p>
|
||
<p>In addition, looking at the code of the Twisted library, there are many use
|
||
cases for replacing internal state constants with enums. The same can be said
|
||
about a lot of networking code (especially implementation of protocols) and
|
||
can be seen in test protocols written with the Tulip library as well.</p>
|
||
</section>
|
||
<section id="acknowledgments">
|
||
<h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2>
|
||
<p>This PEP was initially proposing including the <code class="docutils literal notranslate"><span class="pre">flufl.enum</span></code> package <a class="footnote-reference brackets" href="#id17" id="id9">[8]</a>
|
||
by Barry Warsaw into the stdlib, and is inspired in large parts by it.
|
||
Ben Finney is the author of the earlier enumeration <a class="pep reference internal" href="../pep-0354/" title="PEP 354 – Enumerations in Python">PEP 354</a>.</p>
|
||
</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="id10" role="doc-footnote">
|
||
<dt class="label" id="id10">[<a href="#id6">1</a>]</dt>
|
||
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2013-May/126112.html">https://mail.python.org/pipermail/python-dev/2013-May/126112.html</a></aside>
|
||
<aside class="footnote brackets" id="id11" role="doc-footnote">
|
||
<dt class="label" id="id11">[<a href="#id1">3</a>]</dt>
|
||
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2013-January/019003.html">https://mail.python.org/pipermail/python-ideas/2013-January/019003.html</a></aside>
|
||
<aside class="footnote brackets" id="id12" role="doc-footnote">
|
||
<dt class="label" id="id12">[<a href="#id2">4</a>]</dt>
|
||
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2013-February/019373.html">https://mail.python.org/pipermail/python-ideas/2013-February/019373.html</a></aside>
|
||
<aside class="footnote brackets" id="id13" role="doc-footnote">
|
||
<dt class="label" id="id13">[<a href="#id3">5</a>]</dt>
|
||
<dd>To make enums behave similarly to Python classes like bool, and
|
||
behave in a more intuitive way. It would be surprising if the type of
|
||
<code class="docutils literal notranslate"><span class="pre">Color.red</span></code> would not be <code class="docutils literal notranslate"><span class="pre">Color</span></code>. (Discussion in
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2013-April/125687.html">https://mail.python.org/pipermail/python-dev/2013-April/125687.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id14" role="doc-footnote">
|
||
<dt class="label" id="id14">[6]<em> (<a href='#id4'>1</a>, <a href='#id8'>2</a>, <a href='#id16'>3</a>) </em></dt>
|
||
<dd>Subclassing enums and adding new members creates an unresolvable
|
||
situation; on one hand <code class="docutils literal notranslate"><span class="pre">MoreColor.red</span></code> and <code class="docutils literal notranslate"><span class="pre">Color.red</span></code> should
|
||
not be the same object, and on the other <code class="docutils literal notranslate"><span class="pre">isinstance</span></code> checks become
|
||
confusing if they are not. The discussion also links to Stack Overflow
|
||
discussions that make additional arguments.
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2013-April/125716.html">https://mail.python.org/pipermail/python-dev/2013-April/125716.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id15" role="doc-footnote">
|
||
<dt class="label" id="id15">[<a href="#id5">7</a>]</dt>
|
||
<dd>It may be useful to have a class defining some behavior (methods, with
|
||
no actual enumeration members) mixed into an enum, and this would not
|
||
create the problem discussed in <a class="footnote-reference brackets" href="#id14" id="id16">[6]</a>. (Discussion in
|
||
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2013-May/125859.html">https://mail.python.org/pipermail/python-dev/2013-May/125859.html</a>)</aside>
|
||
<aside class="footnote brackets" id="id17" role="doc-footnote">
|
||
<dt class="label" id="id17">[<a href="#id9">8</a>]</dt>
|
||
<dd><a class="reference external" href="http://pythonhosted.org/flufl.enum/">http://pythonhosted.org/flufl.enum/</a></aside>
|
||
<aside class="footnote brackets" id="id18" role="doc-footnote">
|
||
<dt class="label" id="id18">[<a href="#id7">9</a>]</dt>
|
||
<dd><a class="reference external" href="http://docs.python.org/3/howto/descriptor.html">http://docs.python.org/3/howto/descriptor.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-0435.rst">https://github.com/python/peps/blob/main/peps/pep-0435.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0435.rst">2023-09-09 17:39:29 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="#status-of-discussions">Status of discussions</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
||
<li><a class="reference internal" href="#module-and-type-name">Module and type name</a></li>
|
||
<li><a class="reference internal" href="#proposed-semantics-for-the-new-enumeration-type">Proposed semantics for the new enumeration type</a><ul>
|
||
<li><a class="reference internal" href="#creating-an-enum">Creating an Enum</a></li>
|
||
<li><a class="reference internal" href="#programmatic-access-to-enumeration-members">Programmatic access to enumeration members</a></li>
|
||
<li><a class="reference internal" href="#duplicating-enum-members-and-values">Duplicating enum members and values</a></li>
|
||
<li><a class="reference internal" href="#comparisons">Comparisons</a></li>
|
||
<li><a class="reference internal" href="#allowed-members-and-attributes-of-enumerations">Allowed members and attributes of enumerations</a></li>
|
||
<li><a class="reference internal" href="#restricted-subclassing-of-enumerations">Restricted subclassing of enumerations</a></li>
|
||
<li><a class="reference internal" href="#intenum">IntEnum</a></li>
|
||
<li><a class="reference internal" href="#other-derived-enumerations">Other derived enumerations</a></li>
|
||
<li><a class="reference internal" href="#pickling">Pickling</a></li>
|
||
<li><a class="reference internal" href="#functional-api">Functional API</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#proposed-variations">Proposed variations</a><ul>
|
||
<li><a class="reference internal" href="#flufl-enum">flufl.enum</a></li>
|
||
<li><a class="reference internal" href="#not-having-to-specify-values-for-enums">Not having to specify values for enums</a></li>
|
||
<li><a class="reference internal" href="#using-special-names-or-forms-to-auto-assign-enum-values">Using special names or forms to auto-assign enum values</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#use-cases-in-the-standard-library">Use-cases in the standard library</a></li>
|
||
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0435.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> |