<pre><code>from enum import Enum
class classproperty(object):
"""A class property decorator"""
def __init__(self, getter):
self.getter = getter
def __get__(self, instance, owner):
return self.getter(owner)
class classconstant(object):
"""A constant property from given value,
visible in class and instances"""
def __init__(self, value):
self.value = value
def __get__(self, instance, owner):
return self.value
class strictclassconstant(classconstant):
"""A constant property that is
callable only from the class """
def __get__(self, instance, owner):
if instance:
raise AttributeError(
"Strict class constants are not available in instances")
return self.value
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)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
G = classconstant(6.67300E-11)
@property
def surface_gravity(self):
# universal gravitational constant (m3 kg-1 s-2)
return Planet.G * self.mass / (self.radius * self.radius)
print(Planet.MERCURY.surface_gravity)
print(Planet.G)
print(Planet.MERCURY.G)
class ConstantExample(Enum):
HAM = 1
SPAM = 2
@classproperty
def c1(cls):
return 1
c2 = classconstant(2)
c3 = strictclassconstant(3)
print(ConstantExample.c1, ConstantExample.HAM.c1)
print(ConstantExample.c2, ConstantExample.SPAM.c2)
print(ConstantExample.c3)
# This should fail:
print(ConstantExample.HAM.c3)
</code></pre>
<p>@property不起作用而classconstant起作用的原因非常简单,并在<a href="https://stackoverflow.com/a/6193656/918959">answer here</a>中解释</p>
<blockquote>
<p>The reason that the actual property object is returned when you access
it via a class Hello.foo lies in how the property implements the
<code>__get__(self, instance, owner)</code> special method. If a descriptor is accessed on an instance, then that instance is passed as the
appropriate argument, and owner is the class of that instance.</p>
<p>On the other hand, if it is accessed through the class, then instance
is None and only owner is passed. <em>The property object recognizes this
and returns self.</em></p>
</blockquote>
<p>因此,<code>classproperty</code>中的代码实际上是<code>property</code>的泛化,缺少<code>if instance is None</code>部分。</p>