python-peps/pep-0435/index.html

750 lines
63 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </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 &lt;barry&#32;&#97;t&#32;python.org&gt;,
Eli Bendersky &lt;eliben&#32;&#97;t&#32;gmail.com&gt;,
Ethan Furman &lt;ethan&#32;&#97;t&#32;stoneleaf.us&gt;</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, its
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 isnt 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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&lt;Color.red: 1&gt;</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">&gt;&gt;&gt; </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">&lt;Enum &#39;Color&#39;&gt;</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt;</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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">apples</span> <span class="o">=</span> <span class="p">{}</span>
<span class="gp">&gt;&gt;&gt; </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">&#39;red delicious&#39;</span>
<span class="gp">&gt;&gt;&gt; </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">&#39;granny smith&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">apples</span>
<span class="go">{&lt;Color.red: 1&gt;: &#39;red delicious&#39;, &lt;Color.green: 2&gt;: &#39;granny smith&#39;}</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 its useful to access members in enumerations programmatically (i.e.
situations where <code class="docutils literal notranslate"><span class="pre">Color.red</span></code> wont 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">&gt;&gt;&gt; </span><span class="n">Color</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">&lt;Color.red: 1&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Color</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="go">&lt;Color.blue: 3&gt;</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">&gt;&gt;&gt; </span><span class="n">Color</span><span class="p">[</span><span class="s1">&#39;red&#39;</span><span class="p">]</span>
<span class="go">&lt;Color.red: 1&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Color</span><span class="p">[</span><span class="s1">&#39;green&#39;</span><span class="p">]</span>
<span class="go">&lt;Color.green: 2&gt;</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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">Shape</span><span class="o">.</span><span class="n">square</span>
<span class="go">&lt;Shape.square: 2&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Shape</span><span class="o">.</span><span class="n">alias_for_square</span>
<span class="go">&lt;Shape.square: 2&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Shape</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="go">&lt;Shape.square: 2&gt;</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">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">Shape</span><span class="p">)</span>
<span class="go">[&lt;Shape.square: 2&gt;, &lt;Shape.diamond: 1&gt;, &lt;Shape.circle: 3&gt;]</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">&gt;&gt;&gt; </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">(&#39;square&#39;, &lt;Shape.square: 2&gt;)</span>
<span class="go">(&#39;diamond&#39;, &lt;Shape.diamond: 1&gt;)</span>
<span class="go">(&#39;circle&#39;, &lt;Shape.circle: 3&gt;)</span>
<span class="go">(&#39;alias_for_square&#39;, &lt;Shape.square: 2&gt;)</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">&gt;&gt;&gt; </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">[&#39;alias_for_square&#39;]</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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">Color</span><span class="o">.</span><span class="n">red</span> <span class="o">&lt;</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">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">unorderable types: Color() &lt; 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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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 doesnt 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">&#39;my custom str! </span><span class="si">{0}</span><span class="s1">&#39;</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">&gt;&gt;&gt; </span><span class="n">Mood</span><span class="o">.</span><span class="n">favorite_mood</span><span class="p">()</span>
<span class="go">&lt;Mood.happy: 3&gt;</span>
<span class="gp">&gt;&gt;&gt; </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">(&#39;happy&#39;, 3)</span>
<span class="gp">&gt;&gt;&gt; </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">&#39;my custom str! 1&#39;</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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">IntEnum</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">Shape</span> <span class="o">==</span> <span class="mi">1</span>
<span class="go">False</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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 cant 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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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 youd expect:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">,</span> <span class="s1">&#39;b&#39;</span><span class="p">,</span> <span class="s1">&#39;c&#39;</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">&#39;b&#39;</span>
<span class="gp">&gt;&gt;&gt; </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
theres 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 dont 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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">Animal</span> <span class="o">=</span> <span class="n">Enum</span><span class="p">(</span><span class="s1">&#39;Animal&#39;</span><span class="p">,</span> <span class="s1">&#39;ant bee cat dog&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Animal</span>
<span class="go">&lt;Enum &#39;Animal&#39;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Animal</span><span class="o">.</span><span class="n">ant</span>
<span class="go">&lt;Animal.ant: 1&gt;</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">Animal</span><span class="p">)</span>
<span class="go">[&lt;Animal.ant: 1&gt;, &lt;Animal.bee: 2&gt;, &lt;Animal.cat: 3&gt;, &lt;Animal.dog: 4&gt;]</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">&gt;&gt;&gt; </span><span class="n">Animals</span> <span class="o">=</span> <span class="n">Enum</span><span class="p">(</span><span class="s1">&#39;Animals&#39;</span><span class="p">,</span> <span class="s1">&#39;ant bee cat dog&#39;</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">&gt;&gt;&gt; </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.
Heres 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">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">socket</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">family</span> <span class="o">==</span> <span class="mi">2</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </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>