[Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library

Ethan Furman ethan at stoneleaf.us
Fri Apr 26 18:54:07 CEST 2013


On 04/26/2013 09:27 AM, Serhiy Storchaka wrote:
> 26.04.13 18:50, Larry Hastings написав(ла):
>> On 04/26/2013 12:34 AM, Greg Ewing wrote:
>>> Or if, as Guido says, the only sensible things to use
>>> as enum values are ints and strings, just leave anything
>>> alone that isn't one of those.
>>
>> The standard Java documentation on enums:
>>
>>     http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
>>
>> has an example enum of a "Planet", a small record type containing mass
>> and radius--each of which are floats.  I don't know whether or not it
>> constitutes good programming, but I'd be crestfallen if Java enums were
>> more expressive than Python enums ;-)
>
> This example requires more than features discussed here. It requires an
> enum constructor.
>
> This can't work because the name Planet in the class definition is not
> defined.


The metaclass can define it easily:

   - have generic helper class (I call mine `attrs`)
   - __prepare__ creates an instance of the custom dict
   - __prepare__ then inserts the helper class into the custom dict with 
the same name as the (to be created) custom Enum type
   - return the custom dict to Python

class is processed using custom dict

   - __new__ gets the custom dict back from Python
   - __new__ replaces all instances of the helper class with actual Enum 
instances (which it creates on the spot)
   - any other housekeeping necessary
   - __new__ returns the new Enum type, complete with all Enum instances

Here's an example run:

8<----------planets.py------------------------------------------------
from aenum import Enum

class Planet(Enum):
     MERCURY = Planet(3.303e+23, 2.4397e6)
     VENUS   = Planet(4.869e+24, 6.0518e6)
     EARTH   = Planet(5.976e+24, 6.37814e6)
     MARS    = Planet(6.421e+23, 3.3972e6)
     JUPITER = Planet(1.9e+27,   7.1492e7)
     SATURN  = Planet(5.688e+26, 6.0268e7)
     URANUS  = Planet(8.686e+25, 2.5559e7)
     NEPTUNE = Planet(1.024e+26, 2.4746e7)

     def __init__(self, mass, radius):
         self.mass = mass     # in kilograms
         self.radius = radius # in meters

     @property
     def surfaceGravity(self):
         # universal gravitational constant  (m3 kg-1 s-2)
         G = 6.67300E-11
         return G * self.mass / (self.radius * self.radius)

     def surfaceWeight(self, otherMass):
         return otherMass * self.surfaceGravity

print(int(Planet.VENUS))
print(repr(Planet.VENUS))
print(Planet.VENUS.surfaceGravity)
8<----------planets.py------------------------------------------------

8<----------actual run------------------------------------------------
2
Planet('VENUS', 4.869e+24, 6051800.0, integer=2)
8.871391908774457
8<----------actual run------------------------------------------------

--
~Ethan~


More information about the Python-Dev mailing list