2019-04-21 11:50:48 +08:00

298 lines
81 KiB
HTML
Raw 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.

<div class="body" role="main"><div class="section" id="module-enum"><h1><span class="yiyi-st" id="yiyi-10">8.13. <a class="reference internal" href="#module-enum" title="enum: Implementation of an enumeration class."><code class="xref py py-mod docutils literal"><span class="pre">enum</span></code></a> - 支持枚举</span></h1><div class="versionadded"><p><span class="yiyi-st" id="yiyi-11"><span class="versionmodified">版本3.4中的新功能。</span></span></p></div><p><span class="yiyi-st" id="yiyi-12"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/enum.py">Lib/enum.py</a></span></p><p><span class="yiyi-st" id="yiyi-13">枚举是一组绑定到唯一的常量值的符号名(成员)。</span><span class="yiyi-st" id="yiyi-14">在枚举中,可以通过身份来比较成员,并且可以迭代枚举本身。</span></p><div class="section" id="module-contents"><h2><span class="yiyi-st" id="yiyi-15">8.13.1.</span><span class="yiyi-st" id="yiyi-16">模块内容</span></h2><p><span class="yiyi-st" id="yiyi-17">此模块定义了两个枚举类,可用于定义唯一的名称和值集:<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a><a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a></span><span class="yiyi-st" id="yiyi-18">它还定义了一个装饰器<a class="reference internal" href="#enum.unique" title="enum.unique"><code class="xref py py-func docutils literal"><span class="pre">unique()</span></code></a></span></p><dl class="class"><dt id="enum.Enum"><span class="yiyi-st" id="yiyi-19"><em class="property">class </em><code class="descclassname">enum.</code><code class="descname">Enum</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-20">用于创建枚举常量的基类。</span><span class="yiyi-st" id="yiyi-21">有关替代构造语法,请参见<a class="reference internal" href="#functional-api">Functional API</a>一节。</span></p></dd></dl><dl class="class"><dt id="enum.IntEnum"><span class="yiyi-st" id="yiyi-22"><em class="property">class </em><code class="descclassname">enum.</code><code class="descname">IntEnum</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-23">用于创建枚举常量的基类,也是<a class="reference internal" href="functions.html#int" title="int"><code class="xref py py-class docutils literal"><span class="pre">int</span></code></a>的子类。</span></p></dd></dl><dl class="function"><dt id="enum.unique"><span class="yiyi-st" id="yiyi-24"><code class="descclassname">enum.</code><code class="descname">unique</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-25">枚举类装饰器,确保只有一个名称绑定到任何一个值。</span></p></dd></dl></div><div class="section" id="creating-an-enum"><h2><span class="yiyi-st" id="yiyi-26">8.13.2.</span><span class="yiyi-st" id="yiyi-27">创建枚举</span></h2><p><span class="yiyi-st" id="yiyi-28">枚举是使用<a class="reference internal" href="../reference/compound_stmts.html#class"><code class="xref std std-keyword docutils literal"><span class="pre">class</span></code></a>语法创建的,这使得它们易于读写。</span><span class="yiyi-st" id="yiyi-29"><a class="reference internal" href="#functional-api">Functional API</a>中描述了另一种创建方法。</span><span class="yiyi-st" id="yiyi-30">要定义枚举,子类<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>如下:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">enum</span> <span class="k">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>
<span class="gp">...</span>
</code></pre><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-31">注意</span></p><p><span class="yiyi-st" id="yiyi-32">命名</span></p><ul class="last simple"><li><span class="yiyi-st" id="yiyi-33"><code class="xref py py-class docutils literal"><span class="pre">Color</span></code><em>枚举</em>(或<em>枚举</em></span></li><li><span class="yiyi-st" id="yiyi-34">属性<code class="xref py py-attr docutils literal"><span class="pre">Color.red</span></code><code class="xref py py-attr docutils literal"><span class="pre">Color.green</span></code>等是<em>枚举成员</em>(或<em>枚举成员</em>)。</span></li><li><span class="yiyi-st" id="yiyi-35">枚举成员具有<em>名称</em><em></em><code class="xref py py-attr docutils literal"><span class="pre">Color.red</span></code>的名称为<code class="docutils literal"><span class="pre">red</span></code>,值<code class="xref py py-attr docutils literal"><span class="pre">Color.blue</span></code><code class="docutils literal"><span class="pre">3</span></code>等)</span></li></ul></div><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-36">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-37">即使我们使用<a class="reference internal" href="../reference/compound_stmts.html#class"><code class="xref std std-keyword docutils literal"><span class="pre">class</span></code></a>语法创建枚举枚举不是正常的Python类。</span><span class="yiyi-st" id="yiyi-38">请参阅<a class="reference internal" href="#how-are-enums-different">枚举如何不同?</a></span><span class="yiyi-st" id="yiyi-39">更多细节。</span></p></div><p><span class="yiyi-st" id="yiyi-40">枚举成员具有可读的字符串表示形式:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-41">...而他们的<code class="docutils literal"><span class="pre">repr</span></code>有更多信息:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-42">枚举成员的<em>类型</em>是它所属的枚举:</span></p><pre><code class="language-python"><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 'Color'&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="go">&gt;&gt;&gt;</span>
</code></pre><p><span class="yiyi-st" id="yiyi-43">枚举成员还具有只包含其项目名称的属性:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-44">枚举按定义顺序支持迭代:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-45">枚举成员是可哈希的,因此它们可以在字典和集合中使用:</span></p><pre><code class="language-python"><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">'red delicious'</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">'granny smith'</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">apples</span> <span class="o">==</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="s1">'red delicious'</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="s1">'granny smith'</span><span class="p">}</span>
<span class="go">True</span>
</code></pre></div><div class="section" id="programmatic-access-to-enumeration-members-and-their-attributes"><h2><span class="yiyi-st" id="yiyi-46">8.13.3.</span><span class="yiyi-st" id="yiyi-47">对枚举成员及其属性的编程访问</span></h2><p><span class="yiyi-st" id="yiyi-48">有时,以编程方式访问枚举中的成员是有用的。</span><span class="yiyi-st" id="yiyi-49"><code class="docutils literal"><span class="pre">Color.red</span></code>将不会执行的情况,因为在程序编写时不知道确切的颜色)。</span><span class="yiyi-st" id="yiyi-50"><code class="docutils literal"><span class="pre">Enum</span></code>允许此类访问:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-51">如果要通过<em>名称</em>访问枚举成员,请使用项目访问:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Color</span><span class="p">[</span><span class="s1">'red'</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">'green'</span><span class="p">]</span>
<span class="go">&lt;Color.green: 2&gt;</span>
</code></pre><p><span class="yiyi-st" id="yiyi-52">如果您有一个枚举成员,需要<code class="xref py py-attr docutils literal"><span class="pre">name</span></code><code class="xref py py-attr docutils literal"><span class="pre">value</span></code></span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">member</span> <span class="o">=</span> <span class="n">Color</span><span class="o">.</span><span class="n">red</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">member</span><span class="o">.</span><span class="n">name</span>
<span class="go">'red'</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">member</span><span class="o">.</span><span class="n">value</span>
<span class="go">1</span>
</code></pre></div><div class="section" id="duplicating-enum-members-and-values"><h2><span class="yiyi-st" id="yiyi-53">8.13.4.</span><span class="yiyi-st" id="yiyi-54">复制枚举成员和值</span></h2><p><span class="yiyi-st" id="yiyi-55">有两个具有相同名称的枚举成员无效:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-56">但是,两个枚举成员允许具有相同的值。</span><span class="yiyi-st" id="yiyi-57">给定两个成员A和B具有相同的值并且A首先定义B是A的别名。A和B的值的值的查找将返回A. B的按名称查找也将返回A</span></p><pre><code class="language-python"><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>
</code></pre><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-58">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-59">尝试创建与已定义属性(另一个成员,方法等)具有相同名称的成员,</span><span class="yiyi-st" id="yiyi-60">或者尝试创建与成员具有相同名称的属性。</span></p></div></div><div class="section" id="ensuring-unique-enumeration-values"><h2><span class="yiyi-st" id="yiyi-61">8.13.5.</span><span class="yiyi-st" id="yiyi-62">确保唯一枚举值</span></h2><p><span class="yiyi-st" id="yiyi-63">默认情况下,枚举允许多个名称作为同一值的别名。</span><span class="yiyi-st" id="yiyi-64">当不需要此行为时,可以使用以下装饰器来确保每个值在枚举中仅使用一次:</span></p><dl class="function"><dt><span class="yiyi-st" id="yiyi-65"><code class="descclassname">@</code><code class="descclassname">enum.</code><code class="descname">unique</code></span></dt><dd></dd></dl><p><span class="yiyi-st" id="yiyi-66">专用于枚举的<a class="reference internal" href="../reference/compound_stmts.html#class"><code class="xref std std-keyword docutils literal"><span class="pre">class</span></code></a>装饰器。</span><span class="yiyi-st" id="yiyi-67">它搜索枚举的<code class="xref py py-attr docutils literal"><span class="pre">__members__</span></code>收集找到的任何别名;如果发现任何<a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a>引发的细节:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">enum</span> <span class="k">import</span> <span class="n">Enum</span><span class="p">,</span> <span class="n">unique</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nd">@unique</span>
<span class="gp">... </span><span class="k">class</span> <span class="nc">Mistake</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">one</span> <span class="o">=</span> <span class="mi">1</span>
<span class="gp">... </span> <span class="n">two</span> <span class="o">=</span> <span class="mi">2</span>
<span class="gp">... </span> <span class="n">three</span> <span class="o">=</span> <span class="mi">3</span>
<span class="gp">... </span> <span class="n">four</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">ValueError</span>: <span class="n">duplicate values found in &lt;enum 'Mistake'&gt;: four -&gt; three</span>
</code></pre></div><div class="section" id="iteration"><h2><span class="yiyi-st" id="yiyi-68">8.13.6.</span><span class="yiyi-st" id="yiyi-69">迭代</span></h2><p><span class="yiyi-st" id="yiyi-70">迭代枚举的成员不提供别名:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-71">特殊属性<code class="docutils literal"><span class="pre">__members__</span></code>是将名称映射到成员的有序字典。</span><span class="yiyi-st" id="yiyi-72">它包括枚举中定义的所有名称,包括别名:</span></p><pre><code class="language-python"><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">('square', &lt;Shape.square: 2&gt;)</span>
<span class="go">('diamond', &lt;Shape.diamond: 1&gt;)</span>
<span class="go">('circle', &lt;Shape.circle: 3&gt;)</span>
<span class="go">('alias_for_square', &lt;Shape.square: 2&gt;)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-73"><code class="docutils literal"><span class="pre">__members__</span></code>属性可用于详细编程访问枚举成员。</span><span class="yiyi-st" id="yiyi-74">例如,查找所有别名:</span></p><pre><code class="language-python"><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">['alias_for_square']</span>
</code></pre></div><div class="section" id="comparisons"><h2><span class="yiyi-st" id="yiyi-75">8.13.7.</span><span class="yiyi-st" id="yiyi-76">比较</span></h2><p><span class="yiyi-st" id="yiyi-77">枚举成员通过身份进行比较:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-78">枚举值之间的顺序比较是 <em></em> 受支持。</span><span class="yiyi-st" id="yiyi-79">枚举成员不是整数类型 (但请参见下文 <a class="reference internal" href="#intenum">IntEnum</a></span></p><pre><code class="language-python"><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">"&lt;stdin&gt;"</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>
</code></pre><p><span class="yiyi-st" id="yiyi-80">然而相等比较是已经定义了的︰</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-81">与非枚举类型的比较结果始终是不相等的 (再次,<a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a> 被显式设计的有不同表现,见下文)︰</span></p><pre><code class="language-python"><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>
</code></pre></div><div class="section" id="allowed-members-and-attributes-of-enumerations"><h2><span class="yiyi-st" id="yiyi-82">8.13.8.</span><span class="yiyi-st" id="yiyi-83">允许枚举的成员和属性</span></h2><p><span class="yiyi-st" id="yiyi-84">上面的示例使用整数作为枚举值。</span><span class="yiyi-st" id="yiyi-85">使用整数是简短且方便的(默认情况下由<a class="reference internal" href="#functional-api">Functional API</a>提供),但不是严格强制执行。</span><span class="yiyi-st" id="yiyi-86">在绝大多数用例中,人们不关心枚举的实际值。</span><span class="yiyi-st" id="yiyi-87">但是,如果值<em></em>很重要,枚举可以具有任意值。</span></p><p><span class="yiyi-st" id="yiyi-88">枚举是Python类可以有通常的方法和特殊方法。</span><span class="yiyi-st" id="yiyi-89">如果我们有这个枚举:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </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="gp">... </span> <span class="n">funky</span> <span class="o">=</span> <span class="mi">1</span>
<span class="gp">... </span> <span class="n">happy</span> <span class="o">=</span> <span class="mi">3</span>
<span class="gp">...</span>
<span class="gp">... </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="gp">... </span> <span class="c1"># self is the member here</span>
<span class="gp">... </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="gp">...</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </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="gp">...</span>
<span class="gp">... </span> <span class="nd">@classmethod</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">favorite_mood</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
<span class="gp">... </span> <span class="c1"># cls here is the enumeration</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">cls</span><span class="o">.</span><span class="n">happy</span>
<span class="gp">...</span>
</code></pre><p><span class="yiyi-st" id="yiyi-90">然后:</span></p><pre><code class="language-python"><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">('happy', 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">'my custom str! 1'</span>
</code></pre><p><span class="yiyi-st" id="yiyi-91">允许的规则如下:以单个下划线开始和结束的名称由枚举保留,不能使用;枚举中定义的所有其他属性将成为该枚举的成员,除了特殊方法(<a class="reference internal" href="../reference/datamodel.html#object.__str__" title="object.__str__"><code class="xref py py-meth docutils literal"><span class="pre">__str__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-meth docutils literal"><span class="pre">__add__()</span></code></a>等)</span><span class="yiyi-st" id="yiyi-92">和描述器(方法也是描述器)。</span></p><p><span class="yiyi-st" id="yiyi-93">注意:如果枚举定义<a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a>和/或<a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal"><span class="pre">__init__()</span></code></a>,那么枚举成员的任何值都将传递到这些方法中。</span><span class="yiyi-st" id="yiyi-94">有关示例,请参阅<a class="reference internal" href="#planet">Planet</a></span></p></div><div class="section" id="restricted-subclassing-of-enumerations"><h2><span class="yiyi-st" id="yiyi-95">8.13.9.</span><span class="yiyi-st" id="yiyi-96">枚举的子类化</span></h2><p><span class="yiyi-st" id="yiyi-97">只有枚举没有定义任何成员时,才允许子类化枚举。</span><span class="yiyi-st" id="yiyi-98">所以这是禁止的:</span></p><pre><code class="language-python"><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="gt">Traceback (most recent call last):</span>
<span class="c">...</span>
<span class="gr">TypeError</span>: <span class="n">Cannot extend enumerations</span>
</code></pre><p><span class="yiyi-st" id="yiyi-99">但这是允许的:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-100">允许定义成员的枚举的子类化将导致违反类型和实例的一些重要的不变量。</span><span class="yiyi-st" id="yiyi-101">另一方面,允许在一组枚举之间共享一些常见行为是有意义的。</span><span class="yiyi-st" id="yiyi-102">(有关示例,请参见<a class="reference internal" href="#orderedenum">OrderedEnum</a>。)</span></p></div><div class="section" id="pickling"><h2><span class="yiyi-st" id="yiyi-103">8.13.10.</span><span class="yiyi-st" id="yiyi-104">Pickling</span></h2><p><span class="yiyi-st" id="yiyi-105">枚举可以被pickled和unpickled</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">test.test_enum</span> <span class="k">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="k">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>
</code></pre><p><span class="yiyi-st" id="yiyi-106">酸洗的通常限制适用pickleable枚举必须在模块的顶层定义因为unpickling要求它们可从该模块导入。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-107">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-108">使用pickle协议版本4可以很容易地腌排嵌套在其他类中的枚举。</span></p></div><p><span class="yiyi-st" id="yiyi-109">可以通过定义枚举类中的<a class="reference internal" href="pickle.html#object.__reduce_ex__" title="object.__reduce_ex__"><code class="xref py py-meth docutils literal"><span class="pre">__reduce_ex__()</span></code></a>来修改枚举成员如何进行pickle / unpickled。</span></p></div><div class="section" id="functional-api"><h2><span class="yiyi-st" id="yiyi-110">8.13.11.</span><span class="yiyi-st" id="yiyi-111">函数API </span></h2><p><span class="yiyi-st" id="yiyi-112"><a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>类是可调用的提供以下功能API</span></p><pre><code class="language-python"><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">'Animal'</span><span class="p">,</span> <span class="s1">'ant bee cat dog'</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Animal</span>
<span class="go">&lt;enum 'Animal'&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>
</code></pre><p><span class="yiyi-st" id="yiyi-113">此API的语义类似于<a class="reference internal" href="collections.html#collections.namedtuple" title="collections.namedtuple"><code class="xref py py-class docutils literal"><span class="pre">namedtuple</span></code></a></span><span class="yiyi-st" id="yiyi-114">调用<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>的第一个参数是枚举的名称。</span></p><p><span class="yiyi-st" id="yiyi-115">第二个参数是枚举成员名称的<em></em></span><span class="yiyi-st" id="yiyi-116">它可以是空格分隔的名称字符串,名称序列,具有键/值对的2元组序列或者映射例如</span><span class="yiyi-st" id="yiyi-117">字典)。</span><span class="yiyi-st" id="yiyi-118">最后两个选项允许将任意值分配给枚举其他自动分配从1开始递增的整数使用<code class="docutils literal"><span class="pre">start</span></code>参数指定不同的起始值)。</span><span class="yiyi-st" id="yiyi-119">将返回从<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>派生的新类。</span><span class="yiyi-st" id="yiyi-120">换句话说,上面对<code class="xref py py-class docutils literal"><span class="pre">Animal</span></code>的赋值等价于:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">Animal</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>
<span class="gp">...</span>
</code></pre><p><span class="yiyi-st" id="yiyi-121">默认为<code class="docutils literal"><span class="pre">1</span></code>作为起始号而不是<code class="docutils literal"><span class="pre">0</span></code>的原因是,布尔意义上的<code class="docutils literal"><span class="pre">0</span></code><code class="docutils literal"><span class="pre">False</span></code> ,但枚举成员都计算为<code class="docutils literal"><span class="pre">True</span></code></span></p><p><span class="yiyi-st" id="yiyi-122">使用功能API创建的pickling枚举可能很棘手因为帧堆栈实现细节用于尝试和找出枚举创建在哪个模块。</span><span class="yiyi-st" id="yiyi-123">如果在单独的模块中使用实用程序函数它也会失败并且也可能无法在IronPython或Jython上工作</span><span class="yiyi-st" id="yiyi-124">解决方案是明确指定模块名称如下:</span></p><pre><code class="language-python"><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">'Animal'</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="n">__name__</span><span class="p">)</span>
</code></pre><div class="admonition warning"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-125">警告</span></p><p class="last"><span class="yiyi-st" id="yiyi-126">如果未提供<code class="docutils literal"><span class="pre">module</span></code>并且Enum无法确定它是什么则新的Enum成员将不会取消拆分为了使错误更接近源pickling将被禁用。</span></p></div><p><span class="yiyi-st" id="yiyi-127">在某些情况下新的pickle协议4还依赖于<a class="reference internal" href="stdtypes.html#definition.__qualname__" title="definition.__qualname__"><code class="xref py py-attr docutils literal"><span class="pre">__qualname__</span></code></a>被设置为pickle将能够找到类的位置。</span><span class="yiyi-st" id="yiyi-128">例如如果类在全局范围中的SomeData类中可用</span></p><pre><code class="language-python"><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">'Animal'</span><span class="p">,</span> <span class="s1">'ant bee cat dog'</span><span class="p">,</span> <span class="n">qualname</span><span class="o">=</span><span class="s1">'SomeData.Animal'</span><span class="p">)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-129">完整的声明是:</span></p><pre><code class="language-python"><span></span><span class="n">Enum</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="s1">'NewEnumName'</span><span class="p">,</span> <span class="n">names</span><span class="o">=&lt;...&gt;</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">module</span><span class="o">=</span><span class="s1">'...'</span><span class="p">,</span> <span class="n">qualname</span><span class="o">=</span><span class="s1">'...'</span><span class="p">,</span> <span class="nb">type</span><span class="o">=&lt;</span><span class="n">mixed</span><span class="o">-</span><span class="ow">in</span> <span class="n">class</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</code></pre><table class="docutils field-list" frame="void" rules="none"><tbody valign="top"><tr class="field-odd field"><th class="field-name"><span class="yiyi-st" id="yiyi-130">值:</span></th><td class="field-body"><p class="first"><span class="yiyi-st" id="yiyi-131">新的Enum类将记录为它的名称。</span></p></td></tr><tr class="field-even field"><th class="field-name"><span class="yiyi-st" id="yiyi-132">名称:</span></th><td class="field-body"><p class="first"><span class="yiyi-st" id="yiyi-133">枚举成员。</span><span class="yiyi-st" id="yiyi-134">这可以是空格或逗号分隔的字符串除非另有说明否则值将从1开始</span></p><pre><code class="language-python"><span></span><span class="s1">'red green blue'</span> <span class="o">|</span> <span class="s1">'red,green,blue'</span> <span class="o">|</span> <span class="s1">'red, green, blue'</span>
</code></pre><p><span class="yiyi-st" id="yiyi-135">或名称的迭代器:</span></p><pre><code class="language-python"><span></span><span class="p">[</span><span class="s1">'red'</span><span class="p">,</span> <span class="s1">'green'</span><span class="p">,</span> <span class="s1">'blue'</span><span class="p">]</span>
</code></pre><p><span class="yiyi-st" id="yiyi-136">或(名称,值)对的迭代器:</span></p><pre><code class="language-python"><span></span><span class="p">[(</span><span class="s1">'cyan'</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="p">(</span><span class="s1">'magenta'</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="p">(</span><span class="s1">'yellow'</span><span class="p">,</span> <span class="mi">6</span><span class="p">)]</span>
</code></pre><p><span class="yiyi-st" id="yiyi-137">或映射:</span></p><pre><code class="language-python"><span></span><span class="p">{</span><span class="s1">'chartreuse'</span><span class="p">:</span> <span class="mi">7</span><span class="p">,</span> <span class="s1">'sea_green'</span><span class="p">:</span> <span class="mi">11</span><span class="p">,</span> <span class="s1">'rosemary'</span><span class="p">:</span> <span class="mi">42</span><span class="p">}</span>
</code></pre></td></tr><tr class="field-odd field"><th class="field-name"><span class="yiyi-st" id="yiyi-138">模块:</span></th><td class="field-body"><p class="first"><span class="yiyi-st" id="yiyi-139">模块的名称其中可以找到新的Enum类。</span></p></td></tr><tr class="field-even field"><th class="field-name"><span class="yiyi-st" id="yiyi-140">qualname</span></th><td class="field-body"><p class="first"><span class="yiyi-st" id="yiyi-141">其中在module可以找到新的Enum类。</span></p></td></tr><tr class="field-odd field"><th class="field-name"><span class="yiyi-st" id="yiyi-142">类型:</span></th><td class="field-body"><p class="first"><span class="yiyi-st" id="yiyi-143">类型混合到新的Enum类中。</span></p></td></tr><tr class="field-even field"><th class="field-name"><span class="yiyi-st" id="yiyi-144">开始:</span></th><td class="field-body"><p class="first last"><span class="yiyi-st" id="yiyi-145">如果只传递名称,则开始计数的数字。</span></p></td></tr></tbody></table><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-146"><span class="versionmodified">在版本3.5中已更改:</span>添加了<em>开始</em>参数。</span></p></div></div><div class="section" id="derived-enumerations"><h2><span class="yiyi-st" id="yiyi-147">8.13.12.</span><span class="yiyi-st" id="yiyi-148">派生枚举</span></h2><div class="section" id="intenum"><h3><span class="yiyi-st" id="yiyi-149">8.13.12.1.</span><span class="yiyi-st" id="yiyi-150">IntEnum </span></h3><p><span class="yiyi-st" id="yiyi-151">提供<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>的变体,其也是<a class="reference internal" href="functions.html#int" title="int"><code class="xref py py-class docutils literal"><span class="pre">int</span></code></a>的子类。</span><span class="yiyi-st" id="yiyi-152"><a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a>的成员可以与整数进行比较;通过扩展,不同类型的整数枚举也可以彼此比较:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">enum</span> <span class="k">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>
</code></pre><p><span class="yiyi-st" id="yiyi-153">但是,它们仍然无法与标准的<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>枚举进行比较:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-154"><a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a>值会以其他方式表现为整数:</span></p><pre><code class="language-python"><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">'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">&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>
</code></pre><p><span class="yiyi-st" id="yiyi-155">对于绝大多数代码,强烈建议使用<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>,因为<a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a>打破了枚举的某些语义承诺(通过与整数相比较,并因此与其他无关的枚举)。</span><span class="yiyi-st" id="yiyi-156">它应该仅在没有其他选择的特殊情况下使用;例如,当整数常量被枚举替代,并且向后兼容性需要仍然期望整数的代码。</span></p></div><div class="section" id="others"><h3><span class="yiyi-st" id="yiyi-157">8.13.12.2.</span><span class="yiyi-st" id="yiyi-158">其他</span></h3><p><span class="yiyi-st" id="yiyi-159">虽然<a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a><a class="reference internal" href="#module-enum" title="enum: Implementation of an enumeration class."><code class="xref py py-mod docutils literal"><span class="pre">enum</span></code></a>模块的一部分,但独立实现将非常简单:</span></p><pre><code class="language-python"><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>
</code></pre><p><span class="yiyi-st" id="yiyi-160">这说明如何定义类似的派生枚举;例如在<a class="reference internal" href="stdtypes.html#str" title="str"><code class="xref py py-class docutils literal"><span class="pre">str</span></code></a>而不是<a class="reference internal" href="functions.html#int" title="int"><code class="xref py py-class docutils literal"><span class="pre">int</span></code></a>中混合的<code class="xref py py-class docutils literal"><span class="pre">StrEnum</span></code></span></p><p><span class="yiyi-st" id="yiyi-161">一些规则:</span></p><ol class="arabic simple"><li><span class="yiyi-st" id="yiyi-162">当子类化<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>时,混合类型必须在基本序列中的<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>之前出现,如上面的<a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a>示例。</span></li><li><span class="yiyi-st" id="yiyi-163">虽然<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>可以包含任何类型的成员,但一旦您混合了其他类型,所有成员必须具有该类型的值。</span><span class="yiyi-st" id="yiyi-164"><a class="reference internal" href="functions.html#int" title="int"><code class="xref py py-class docutils literal"><span class="pre">int</span></code></a></span><span class="yiyi-st" id="yiyi-165">此限制不适用于仅添加方法且不指定其他数据类型(例如<a class="reference internal" href="functions.html#int" title="int"><code class="xref py py-class docutils literal"><span class="pre">int</span></code></a><a class="reference internal" href="stdtypes.html#str" title="str"><code class="xref py py-class docutils literal"><span class="pre">str</span></code></a>)的混合。</span></li><li><span class="yiyi-st" id="yiyi-166">当混合其他数据类型时,<code class="xref py py-attr docutils literal"><span class="pre">value</span></code>属性<em>与枚举成员本身不同</em>,虽然它是等效的,并且将比较相等。</span></li><li><span class="yiyi-st" id="yiyi-167">%格式:<cite>s</cite><cite>r</cite>调用<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>类的<a class="reference internal" href="../reference/datamodel.html#object.__str__" title="object.__str__"><code class="xref py py-meth docutils literal"><span class="pre">__str__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__repr__" title="object.__repr__"><code class="xref py py-meth docutils literal"><span class="pre">__repr__()</span></code></a>其他代码例如IntEnum的<cite>i</cite><cite>h</cite>)将枚举成员视为其混合类型。</span></li><li><span class="yiyi-st" id="yiyi-168"><a class="reference internal" href="stdtypes.html#str.format" title="str.format"><code class="xref py py-meth docutils literal"><span class="pre">str.format()</span></code></a>(或<a class="reference internal" href="functions.html#format" title="format"><code class="xref py py-func docutils literal"><span class="pre">format()</span></code></a>)将使用混合类型的<a class="reference internal" href="../reference/datamodel.html#object.__format__" title="object.__format__"><code class="xref py py-meth docutils literal"><span class="pre">__format__()</span></code></a></span><span class="yiyi-st" id="yiyi-169">如果需要<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>类的<a class="reference internal" href="stdtypes.html#str" title="str"><code class="xref py py-func docutils literal"><span class="pre">str()</span></code></a><a class="reference internal" href="functions.html#repr" title="repr"><code class="xref py py-func docutils literal"><span class="pre">repr()</span></code></a>,请使用<cite>s</cite><cite>r</cite>格式代码。</span></li></ol></div></div><div class="section" id="interesting-examples"><h2><span class="yiyi-st" id="yiyi-170">8.13.13.</span><span class="yiyi-st" id="yiyi-171">有趣的例子</span></h2><p><span class="yiyi-st" id="yiyi-172">虽然<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a><a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a>预期覆盖大多数用例,但它们无法覆盖所有这些用例。</span><span class="yiyi-st" id="yiyi-173">这里是一些不同类型的枚举的方法,可以直接使用,或者作为创建自己的例子。</span></p><div class="section" id="autonumber"><h3><span class="yiyi-st" id="yiyi-174">8.13.13.1.</span><span class="yiyi-st" id="yiyi-175">自动编号</span></h3><p><span class="yiyi-st" id="yiyi-176">避免必须为每个枚举成员指定值:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">AutoNumber</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">__new__</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">value</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">cls</span><span class="o">.</span><span class="n">__members__</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="gp">... </span> <span class="n">obj</span> <span class="o">=</span> <span class="nb">object</span><span class="o">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">cls</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">obj</span><span class="o">.</span><span class="n">_value_</span> <span class="o">=</span> <span class="n">value</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">obj</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">AutoNumber</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">red</span> <span class="o">=</span> <span class="p">()</span>
<span class="gp">... </span> <span class="n">green</span> <span class="o">=</span> <span class="p">()</span>
<span class="gp">... </span> <span class="n">blue</span> <span class="o">=</span> <span class="p">()</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Color</span><span class="o">.</span><span class="n">green</span><span class="o">.</span><span class="n">value</span> <span class="o">==</span> <span class="mi">2</span>
<span class="go">True</span>
</code></pre><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-177">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-178">如果定义了<a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a>方法则在创建枚举成员期间使用它随后被Enum的<a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a>替换,它在类创建后用于查找现有成员。</span></p></div></div><div class="section" id="orderedenum"><h3><span class="yiyi-st" id="yiyi-179">8.13.13.2.</span><span class="yiyi-st" id="yiyi-180">OrderedEnum </span></h3><p><span class="yiyi-st" id="yiyi-181">不是基于<a class="reference internal" href="#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal"><span class="pre">IntEnum</span></code></a>的有序枚举,因此维持正常的<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>不变量(例如与其他枚举不可比较):</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">OrderedEnum</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">__ge__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="n">other</span><span class="o">.</span><span class="n">__class__</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">&gt;=</span> <span class="n">other</span><span class="o">.</span><span class="n">value</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">NotImplemented</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__gt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="n">other</span><span class="o">.</span><span class="n">__class__</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">&gt;</span> <span class="n">other</span><span class="o">.</span><span class="n">value</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">NotImplemented</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__le__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="n">other</span><span class="o">.</span><span class="n">__class__</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">&lt;=</span> <span class="n">other</span><span class="o">.</span><span class="n">value</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">NotImplemented</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__lt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="n">other</span><span class="o">.</span><span class="n">__class__</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">&lt;</span> <span class="n">other</span><span class="o">.</span><span class="n">value</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">NotImplemented</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">Grade</span><span class="p">(</span><span class="n">OrderedEnum</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">A</span> <span class="o">=</span> <span class="mi">5</span>
<span class="gp">... </span> <span class="n">B</span> <span class="o">=</span> <span class="mi">4</span>
<span class="gp">... </span> <span class="n">C</span> <span class="o">=</span> <span class="mi">3</span>
<span class="gp">... </span> <span class="n">D</span> <span class="o">=</span> <span class="mi">2</span>
<span class="gp">... </span> <span class="n">F</span> <span class="o">=</span> <span class="mi">1</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Grade</span><span class="o">.</span><span class="n">C</span> <span class="o">&lt;</span> <span class="n">Grade</span><span class="o">.</span><span class="n">A</span>
<span class="go">True</span>
</code></pre></div><div class="section" id="duplicatefreeenum"><h3><span class="yiyi-st" id="yiyi-182">8.13.13.3.</span><span class="yiyi-st" id="yiyi-183">DuplicateFreeEnum </span></h3><p><span class="yiyi-st" id="yiyi-184">如果找到重复的成员名称而不是创建别名,则引发错误:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">DuplicateFreeEnum</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">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">cls</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span>
<span class="gp">... </span> <span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">==</span> <span class="n">e</span><span class="o">.</span><span class="n">value</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">cls</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">a</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
<span class="gp">... </span> <span class="n">e</span> <span class="o">=</span> <span class="n">cls</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="o">.</span><span class="n">name</span>
<span class="gp">... </span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
<span class="gp">... </span> <span class="s2">"aliases not allowed in DuplicateFreeEnum: </span><span class="si">%r</span><span class="s2"> --&gt; </span><span class="si">%r</span><span class="s2">"</span>
<span class="gp">... </span> <span class="o">%</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">e</span><span class="p">))</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">DuplicateFreeEnum</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>
<span class="gp">... </span> <span class="n">grene</span> <span class="o">=</span> <span class="mi">2</span>
<span class="gp">...</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="c">...</span>
<span class="gr">ValueError</span>: <span class="n">aliases not allowed in DuplicateFreeEnum: 'grene' --&gt; 'green'</span>
</code></pre><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-185">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-186">这是一个有用的示例用于子类化Enum以添加或更改其他行为以及禁止别名。</span><span class="yiyi-st" id="yiyi-187">如果唯一所需的更改是禁止别名,则可以使用<a class="reference internal" href="#enum.unique" title="enum.unique"><code class="xref py py-func docutils literal"><span class="pre">unique()</span></code></a>装饰器。</span></p></div></div><div class="section" id="planet"><h3><span class="yiyi-st" id="yiyi-188">8.13.13.4.</span><span class="yiyi-st" id="yiyi-189">Planet</span></h3><p><span class="yiyi-st" id="yiyi-190">如果定义<a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal"><span class="pre">__init__()</span></code></a>,则枚举成员的值将传递到这些方法:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">Planet</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">MERCURY</span> <span class="o">=</span> <span class="p">(</span><span class="mf">3.303e+23</span><span class="p">,</span> <span class="mf">2.4397e6</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">VENUS</span> <span class="o">=</span> <span class="p">(</span><span class="mf">4.869e+24</span><span class="p">,</span> <span class="mf">6.0518e6</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">EARTH</span> <span class="o">=</span> <span class="p">(</span><span class="mf">5.976e+24</span><span class="p">,</span> <span class="mf">6.37814e6</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">MARS</span> <span class="o">=</span> <span class="p">(</span><span class="mf">6.421e+23</span><span class="p">,</span> <span class="mf">3.3972e6</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">JUPITER</span> <span class="o">=</span> <span class="p">(</span><span class="mf">1.9e+27</span><span class="p">,</span> <span class="mf">7.1492e7</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">SATURN</span> <span class="o">=</span> <span class="p">(</span><span class="mf">5.688e+26</span><span class="p">,</span> <span class="mf">6.0268e7</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">URANUS</span> <span class="o">=</span> <span class="p">(</span><span class="mf">8.686e+25</span><span class="p">,</span> <span class="mf">2.5559e7</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">NEPTUNE</span> <span class="o">=</span> <span class="p">(</span><span class="mf">1.024e+26</span><span class="p">,</span> <span class="mf">2.4746e7</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mass</span><span class="p">,</span> <span class="n">radius</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">mass</span> <span class="o">=</span> <span class="n">mass</span> <span class="c1"># in kilograms</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">radius</span> <span class="o">=</span> <span class="n">radius</span> <span class="c1"># in meters</span>
<span class="gp">... </span> <span class="nd">@property</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">surface_gravity</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="c1"># universal gravitational constant (m3 kg-1 s-2)</span>
<span class="gp">... </span> <span class="n">G</span> <span class="o">=</span> <span class="mf">6.67300E-11</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">G</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">mass</span> <span class="o">/</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">radius</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">radius</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Planet</span><span class="o">.</span><span class="n">EARTH</span><span class="o">.</span><span class="n">value</span>
<span class="go">(5.976e+24, 6378140.0)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Planet</span><span class="o">.</span><span class="n">EARTH</span><span class="o">.</span><span class="n">surface_gravity</span>
<span class="go">9.802652743337129</span>
</code></pre></div></div><div class="section" id="how-are-enums-different"><h2><span class="yiyi-st" id="yiyi-191">8.13.14.</span><span class="yiyi-st" id="yiyi-192">如何枚举不同?</span></h2><p><span class="yiyi-st" id="yiyi-193">枚举有一个自定义元类它影响派生的Enum类及其实例成员的许多方面。</span></p><div class="section" id="enum-classes"><h3><span class="yiyi-st" id="yiyi-194">8.13.14.1.</span><span class="yiyi-st" id="yiyi-195">枚举类</span></h3><p><span class="yiyi-st" id="yiyi-196">The <code class="xref py py-class docutils literal"><span class="pre">EnumMeta</span></code> metaclass is responsible for providing the <a class="reference internal" href="../reference/datamodel.html#object.__contains__" title="object.__contains__"><code class="xref py py-meth docutils literal"><span class="pre">__contains__()</span></code></a>, <a class="reference internal" href="../reference/datamodel.html#object.__dir__" title="object.__dir__"><code class="xref py py-meth docutils literal"><span class="pre">__dir__()</span></code></a>, <a class="reference internal" href="../reference/datamodel.html#object.__iter__" title="object.__iter__"><code class="xref py py-meth docutils literal"><span class="pre">__iter__()</span></code></a> and other methods that allow one to do things with an <a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a> class that fail on a typical class, such as <cite>list(Color)</cite> or <cite>some_var in Color</cite>. </span><span class="yiyi-st" id="yiyi-197"><code class="xref py py-class docutils literal"><span class="pre">EnumMeta</span></code>负责确保最终<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>类上的各种其他方法正确(例如<a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a><a class="reference internal" href="pickle.html#object.__getnewargs__" title="object.__getnewargs__"><code class="xref py py-meth docutils literal"><span class="pre">__getnewargs__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__str__" title="object.__str__"><code class="xref py py-meth docutils literal"><span class="pre">__str__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__repr__" title="object.__repr__"><code class="xref py py-meth docutils literal"><span class="pre">__repr__()</span></code></a>)。</span></p></div><div class="section" id="enum-members-aka-instances"><h3><span class="yiyi-st" id="yiyi-198">8.13.14.2.</span><span class="yiyi-st" id="yiyi-199">枚举成员(又名实例)</span></h3><p><span class="yiyi-st" id="yiyi-200">Enum成员最有趣的是它们是单例。</span><span class="yiyi-st" id="yiyi-201"><code class="xref py py-class docutils literal"><span class="pre">EnumMeta</span></code>在创建<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>类时创建它们,然后放置自定义<a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a>,以确保没有新的通过仅返回现有成员实例来实例化。</span></p></div><div class="section" id="finer-points"><h3><span class="yiyi-st" id="yiyi-202">8.13.14.3.</span><span class="yiyi-st" id="yiyi-203">精细点</span></h3><p><span class="yiyi-st" id="yiyi-204"><a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>成员是<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>类的实例,即使它们可作为<cite>EnumClass.member</cite>访问,它们不应直接从成员访问因为该查找可能会失败,或者更糟的是,返回除了您正在寻找的<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>成员之外的东西:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">FieldTypes</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">name</span> <span class="o">=</span> <span class="mi">0</span>
<span class="gp">... </span> <span class="n">value</span> <span class="o">=</span> <span class="mi">1</span>
<span class="gp">... </span> <span class="n">size</span> <span class="o">=</span> <span class="mi">2</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">FieldTypes</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">size</span>
<span class="go">&lt;FieldTypes.size: 2&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">FieldTypes</span><span class="o">.</span><span class="n">size</span><span class="o">.</span><span class="n">value</span>
<span class="go">2</span>
</code></pre><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-205"><span class="versionmodified">在版本3.5中更改。</span></span></p></div><p><span class="yiyi-st" id="yiyi-206"><code class="xref py py-attr docutils literal"><span class="pre">__members__</span></code>属性仅在类上可用。</span></p><p><span class="yiyi-st" id="yiyi-207">如果您给予<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>子类额外方法,如上述<a class="reference internal" href="#planet">Planet</a>类,那些方法将显示在成员的<a class="reference internal" href="functions.html#dir" title="dir"><code class="xref py py-func docutils literal"><span class="pre">dir()</span></code></a></span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">Planet</span><span class="p">)</span>
<span class="go">['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">Planet</span><span class="o">.</span><span class="n">EARTH</span><span class="p">)</span>
<span class="go">['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']</span>
</code></pre><p><span class="yiyi-st" id="yiyi-208"><a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a>方法将仅用于创建<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>成员 - 在被替换之后。</span><span class="yiyi-st" id="yiyi-209">任何自定义<a class="reference internal" href="../reference/datamodel.html#object.__new__" title="object.__new__"><code class="xref py py-meth docutils literal"><span class="pre">__new__()</span></code></a>方法都必须创建对象,并相应地设置<code class="xref py py-attr docutils literal"><span class="pre">_value_</span></code>属性。</span></p><p><span class="yiyi-st" id="yiyi-210">如果你想改变<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>成员的查找方式,你应该为<a class="reference internal" href="#enum.Enum" title="enum.Enum"><code class="xref py py-class docutils literal"><span class="pre">Enum</span></code></a>子类编写一个辅助函数或<a class="reference internal" href="functions.html#classmethod" title="classmethod"><code class="xref py py-func docutils literal"><span class="pre">classmethod()</span></code></a></span></p></div></div></div></div>