Here are the basic ideas (orientation: C++):
- You are responsible to find names for constants and this code provides a way to give values which differ from each other
 - The context is to allow different enums with values starting by 0
 - If you like to use constants like here: "Orientation.TOP" then place those constants in the relating class
 - You still can assign your own values
 
About the code:
- It's not much code also it might look like (implementation + documentation + unittests)
 - The __docformat__ is for epydoc. Temporarily remove the "@singleton" when trying to generate the HTML documentation (can not yet be handled by epydoc).
 
Example(s): Have a look at the unittests please.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116  | """
    @author  Thomas Lehmann
    @file    enum.py
    @note The singleton example is taken from:
          http://www.python.org/dev/peps/pep-0318/#examples
    @note I don't use TAB's and indentation is 4.
    @note epydoc wrongly interprets the class as a function.
          Probably because of the decorator (without it works).
"""
__docformat__ = "javadoc en"
import inspect
import unittest
def singleton(theClass):
    """ decorator for a class to make a singleton out of it """
    classInstances = {}
    def getInstance():
        """ creating or just return the one and only class instance """
        if theClass not in classInstances:
            classInstances[theClass] = theClass()
        return classInstances[theClass]
    return getInstance
@singleton
class Enum(object):
    """ class for providing enum functionality. An enum in C++ usually looks
        like this: enum { A, B, C }; and the results are 0, 1 and 2 for A, B and C.
        We provide similar functionality means auto incrementing of values for constants
        added to an enum...
        >>> TOP    = enum("direction") # or enum(Direction) when Direction is a class
        >>> LEFT   = enum("direction") # or enum(Direction) when Direction is a class
        >>> RIGHT  = enum("direction") # or enum(Direction) when Direction is a class
        >>> BOTTOM = enum("direction") # or enum(Direction) when Direction is a class
        >>> assert TOP < LEFT < RIGHT < BOTTOM
        <ul>
            <li>You still can assign an individual value.
            <li>You can place constants inside the class (if you like) -> Direction.TOP
            <li>Same to C++: you have to pay attention where new constants are added. When
                you insert it inbetween then you will 'move' the other values.
        </ul>
    """
    def __init__(self):
        """ registered enums """
        self.contexts = {}
    def getNextId(self, context):
        """ providing next id >= 0 on each call per context
            @param context is a string
            @return is an integer value being unique for given context
        """
        if not context in self.contexts:
            self.contexts[context] = -1
        self.contexts[context] += 1
        return self.contexts[context]
def enum(context):
    """ wrapper for calling the singleton. Documentation is placed
        at the class Enum.
        @param context can be a string or a class
        @return is an integer value being unique for given context
    """
    if inspect.isclass(context):
        return Enum().getNextId(context.__name__)
    return Enum().getNextId(context)
class EnumTestCase(unittest.TestCase):
    """ testing of class Enum """
    def testSingleton(self):
        """ testing the singleton mechanism """
        instanceA = Enum()
        instanceB = Enum()
        self.assertEqual(instanceA, instanceB)
    def testGetNextId(self):
        """ example of creating two constants """
        instance   = Enum()
        HORIZONTAL = instance.getNextId("orientation")
        VERTICAL   = instance.getNextId("orientation")
        self.assertTrue(HORIZONTAL < VERTICAL)
    def testEnumFunctionWithStringContext(self):
        """ example of creating four constants with string as context """
        class Direction:
            TOP    = enum("direction")
            LEFT   = enum("direction")
            RIGHT  = enum("direction")
            BOTTOM = enum("direction")
        self.assertTrue(Direction.TOP < Direction.LEFT < Direction.RIGHT < Direction.BOTTOM)
    def testEnumFunctionWithClassContext(self):
        """ example of creating four constants with a class as context
            @note I have tried to move the enum code to the class but this
                  seems not to work """
        class Vector:
            def __init__(self):
                self.vector = [0, 0]
        X = enum(Vector)
        Y = enum(Vector)
        self.assertTrue(X < Y)
        self.assertEqual(X, 0)
        self.assertEqual(Y, 1)
if __name__ == "__main__":
    suite = unittest.TestLoader().loadTestsFromTestCase(EnumTestCase)
    unittest.TextTestRunner(verbosity=3).run(suite)
 | 
In "testEnumFunctionWithClassContext" I have tried to move the enum code to the class but this didn't work. Obviously is the class not fully defined yet:
class Vector:
    X = enum(Vector)
    Y = enum(Vector)
    def __init__(self):
        self.vector = [0, 0]
If you have an idea how this can be done, then please tell me.
    Tags: enum
  
  
Download
Copy to clipboard
You can also use something as simple as a small function, Thomas:
With something so small, you can then do this in the interpreter: