Python enums revisited

Will Ware wware at world.std.com
Thu Aug 23 10:12:06 EDT 2001


Slightly improved version, verifies that enum values are
all unique.
====================================================
""" I once tried to give Python something like C's enums, as
described here:
http://groups.google.com/groups?selm=G6qzLy.6Fo@world.std.com
That approach had the flaw of trying to assign to a dictionary
returned by the locals() function, intending that such assignments
would become class attributes, but that isn't guaranteed to work
as versions of Python change.
"""

import types, string, pprint, exceptions

class EnumException(exceptions.Exception):
    pass

def attachEnums(clas, enumList):
    i = 0
    uniqueValues = [ ]
    for x in enumList:
        if type(x) == types.TupleType:
            x, i = x
        if type(x) != types.StringType:
            raise EnumException, \
                  "enum name is not a string: " + x
        if type(i) != types.IntType:
            raise EnumException, \
                  "enum value is not an integer: " + i
        if i in uniqueValues:
            raise EnumException, \
                  "enum value is not unique for " + x
        uniqueValues.append(i)
        setattr(clas, x, i)
        try: clas.enumNames[i] = x
        except AttributeError: clas.enumNames = {i: x}
        i = i + 1

class MidiEvent:
    """MidiEvent is a class"""
    def __repr__(self):
        # It's handy to be able to reverse-lookup the names of the
        # enum values. C doesn't offer this feature.
        return ("<MidiEvent %s>" %
                (self.enumNames[self.type]))


attachEnums(MidiEvent,
            ["NOTE_ON",
             "NOTE_OFF",
             "ANOTHER_MIDI_EVENT",
             "SOME_OTHER_MIDI_EVENT",
             ("CONTROLLER_CHANGE", 500),
             ("POLYPHONIC_KEY_PRESSURE", 500),
             # many many more...
             ])

for x in string.split(
"""
m = MidiEvent()   # MidiEvent is a class, m is an instance
m.type = MidiEvent.POLYPHONIC_KEY_PRESSURE
print m

# Notice that m's attributes include neither the enums themselves nor
# the enumNames dictionary. These are CLASS attributes, not INSTANCE
# attributes, and that means you can create vast numbers of MidiEvent
# instances with reckless abandon, never worrying that namespaces and
# memory will become cluttered with redundant copies of your enums.
pprint.pprint(MidiEvent.__dict__)
print m.__dict__
""", "\n"):
    if x and x[:1] != '#':
        print ">>>", x
        exec x
    else:
        print x

-- 
-----------------------------------+---------------------
 22nd century: Esperanto, geodesic | Will Ware
 domes, hovercrafts, metric system | wware at world.std.com



More information about the Python-list mailing list