<p>这是高级行为,在创建的90%以上的枚举中不需要它。</p>
<p>根据文件:</p>
<blockquote>
<p>The rules for what is allowed are as follows: <code>_sunder_</code> names (starting and ending with a single underscore) are reserved by enum and cannot be used; all other attributes defined within an enumeration will become members of this enumeration, with the exception of <code>__dunder__</code> names and <code>descriptors</code> (methods are also descriptors).</p>
</blockquote>
<p>所以如果你想要一个类常量,你有几个选择:</p>
<ul>
<li>在<code>__init__</code>中创建</li>
<li>创建类后添加</li>
<li>使用mixin</li>
<li>创建自己的<code>descriptor</code></li>
</ul>
<p>在<code>__init__</code>中创建常量并在创建类之后添加它都会因为没有在一个地方收集所有的类信息而受到影响。</p>
<p>mixin当然可以在适当的时候使用(<a href="https://stackoverflow.com/a/18075283/1733117">see dnozay's answer for a good example</a>),但是也可以通过使用内置了实际常量的基类<code>Enum</code>来简化这种情况。</p>
<p>首先,将在以下示例中使用的常数:</p>
<pre><code>class Constant: # use Constant(object) if in Python 2
def __init__(self, value):
self.value = value
def __get__(self, *args):
return self.value
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.value)
</code></pre>
<p>以及一次性枚举示例:</p>
<pre><code>from enum import Enum
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
# universal gravitational constant
G = Constant(6.67300E-11)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
@property
def surface_gravity(self):
return self.G * self.mass / (self.radius * self.radius)
print(Planet.__dict__['G']) # Constant(6.673e-11)
print(Planet.G) # 6.673e-11
print(Planet.NEPTUNE.G) # 6.673e-11
print(Planet.SATURN.surface_gravity) # 10.44978014597121
</code></pre>
<p>最后,多用途枚举示例:</p>
<pre><code>from enum import Enum
class AstronomicalObject(Enum):
# universal gravitational constant
G = Constant(6.67300E-11)
def __init__(self, mass, radius):
self.mass = mass
self.radius = radius
@property
def surface_gravity(self):
return self.G * self.mass / (self.radius * self.radius)
class Planet(AstronomicalObject):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
class Asteroid(AstronomicalObject):
CERES = (9.4e+20 , 4.75e+5)
PALLAS = (2.068e+20, 2.72e+5)
JUNOS = (2.82e+19, 2.29e+5)
VESTA = (2.632e+20 ,2.62e+5
Planet.MERCURY.surface_gravity # 3.7030267229659395
Asteroid.CERES.surface_gravity # 0.27801085872576176
</code></pre>
<hr/>
<p><strong>注意:</p>
<p>实际上,<code>Constant</code><code>G</code>不是这样的。可以将<code>G</code>重新绑定到其他对象:</p>
<pre><code>Planet.G = 1
</code></pre>
<p>如果您真的需要它是常量(也称为不可重新绑定),那么使用<a href="https://pypi.python.org/pypi/aenum" rel="noreferrer">new aenum library</a>[1],它将阻止重新分配<code>constant</code>s和<code>Enum</code>成员的尝试。</p>
<hr/>
<p><sup>1</sup>披露:我是<a href="https://docs.python.org/3/library/enum.html" rel="noreferrer">Python stdlib ^{<cd4>}</a>、<a href="https://pypi.python.org/pypi/enum34" rel="noreferrer">^{<cd11>} backport</a>和<a href="https://pypi.python.org/pypi/aenum" rel="noreferrer">Advanced Enumeration (^{<cd12>})</a>库的作者。</p>