new enum idiom

Jonathan Polley
Sun Jan 7 15:23:07 EST 2001


Forget about the ordinal/value conversion, I keep thinking in terms of strongly typed
languages (sigh).  I have also modified the enum function so that it no longer needs to
be passed a class, but instantiates one of its own and returns it to the caller.

>>> MIDI_Event = enum.enum ("NOTE_ON", "NOTE_OFF", 3, "POLYPHONIC_KEY_PRESSURE",
"CONTROLLER_CHANGE")
>>> MIDI_Event.NOTE_ON
0
>>> MIDI_Event.POLYPHONIC_KEY_PRESSURE
4


Jonathan Polley
jwpolley at collins.rockwell.com


# module begins

import types

# a private class that will be instantiated for each enumeration
class __Enum_Class:
    # an empty constructor
    def __init__(self):
        pass
    # print out the name of the base class, FWIW
    def __repr__(self):
        return `self.__class__`

def enum(*args, **keys):
    """Create and enumerate to your hearts delight,
    args is a sequence of enumeration names, possibly interleaved
       with values that override the default value by specifying
       the value for the directly preceding enum name.
    **keys is a hack to allow to override the default name (Enum_Repr)
       for the dict used to store the reverse mapping from enum
       value to enum string"""

    # The value of the last added enum
    Last_Enum = -1

    # the dictionary mapping enumerations to values
    Enum_Repr = {}

    # an instance of an enumerated type container
    New_Enum = __Enum_Class()

    # for each argument
    for Enum in args:
        # if I was passed a string enumeration
        if type(Enum) == types.StringType:
            # add one element to the enumeration
            Last_Enum += 1
            # add the value to the enumerated list
            New_Enum.__dict__[Enum] = Last_Enum
            Enum_Repr[Last_Enum] = Enum

        # if not a string, it had better be an integer!
        elif type (Enum) != types.IntType:
            raise ValueError, "Enumeration must be a string or integer"

        # check for a change in the enumeration sequence
        elif Enum > Last_Enum:
            # change the ordinal value of the last enumeration
            New_Enum.__dict__[Enum_Repr[Last_Enum]] = Enum
            # move the enumeration to its new position
            Enum_Repr[Enum] = Enum_Repr[Last_Enum]
            # delete the old position of the enumeration
            del Enum_Repr[Last_Enum]
            # remember the new value of the end of the enumeration
            Last_Enum = Enum

        # check if the enumeration change was backward!
        elif Enum < Last_Enum:
            raise ValueError, "Enumeration value out of bound"

        # end if I was passed a string enumeration
    # end for each argument

    # store the enumeration string in the class' dictionary
    New_Enum.__dict__[keys.get(Enum_Repr, "__Enum_Repr")] = Enum_Repr

    # return the new enumeration to the caller
    return New_Enum

# end def enum

I foolishly wrote:

> Is is possible to modify the 'enum' function so that I don't have to provide a
> class?  I would like to use something like this method to create enumerated types,
> but I don't want to keep generating classes that say:
>
> class Ufda:
>     def __repr__(self):
>         return self.Enum_Repr[self.type]
>
> I would like to just do a:
>
> MIDI_Event = enum("NOTE_ON", "NOTE_OFF", 3, "POLYPHONIC_KEY_PRESSURE",
> "CONTROLLER_CHANGE")
>
> and then do MIDI_Event.NOTE_ON.
>
> On a related note, how would I map between the enumeration and its ordinal value?
> Would I add the methods 'ord' and 'val' to the base class
> (MIDI_Event.ord(MIDI_Event.NOTE_OFF)) yields 3 and MIDI_Event.val(0) yields
> MIDI_Event.NOTE_ON)?
>
> Not being very use to OO and classes, I may need some adult supervision on this  ;)
>
> Thanks,
>
> Jonathan Polley
> jwpolley at collins.rockwell.com
>




More information about the Python-list mailing list