Am I the only one who would love these extentions? - Python 3.0proposals (long)

Tim Jarman tim.jarman at lineone.net
Wed Nov 12 22:51:51 CET 2003


On Wednesday 12 Nov 2003 5:37 pm, Dave Brueck wrote:
> > I like some of your suggestions, like enum.
>
> I wouldn't mind having a standard module include something like this:
>
> class Enumerate(object):
>     def __init__(self, names):
>         for number, name in enumerate(names.split()):
>             setattr(self, name, number)
>
> WORK = Enumerate('NONE WRITE READ SENDFILE CONNECT ACCEPT')
>
> I like it better than C-style enums because it's clear that the element
> comes from a particular enumeration, e.g.:
>
> workFlags = WORK.WRITE
>
> -Dave

I knocked this up when I was after something similar:

<code linewrap_alert="on">
# Utility class to manage a set of named integer constants within a namespace.

class Enum(object):
    """Class to manage a set of named integer constants within a namespace.

    Examples:

    Enum("RED", "GREEN", "BLUE") creates constants RED=1, GREEN=2, BLUE=3.
    Enum(RED=1, GREEN=2, BLUE=4) creates constants RED=1, GREEN=2, BLUE=4.
    Enum("RED", "GREEN", "BLUE", BLACK=0) creates BLACK=0, RED=1, GREEN=2, 
BLUE=3.

    These values are created as attributes of the Enum instance, thus:

    constants = Enum("RED", "GREEN", "BLUE")
    constants.RED               # -> 1
    """
    def __init__(self, *names, **pairs):
            """Create an attribute for each name.

            Positional arguments are assigned a sequential  integer value 
starting from 1.
            Named arguments are assigned the supplied value.
            """
            self._lookup = {}
            value = 1
            for name in names:
                setattr(self, name, value)
                self._lookup[value] = name
                value += 1

            for name, value in pairs.items():
                if hasattr(self, name):
                    raise ValueError("Name %s specified more than once." % 
name)
                setattr(self, name, value)
                self._lookup[value] = name
                value += 1


    def lookup(self, value):
            """Return the name corresponding to a given value.

            Example:

            constants = Enum("RED", "GREEN", "BLUE")
            constants.lookup(1)               # returns "RED"
            """
            return self._lookup[value]

    def isValid(self, value):
            """Return True if value is a valid constant, False otherwise.

            Example:

            constants = Enum("RED", "GREEN", "BLUE")
            constants.isValid(1)              # returns True
            constants.isValid(42)             # returns False
            """
            return self._lookup.has_key(value)

    def __repr__(self):
            """Make a nice description of enum contents."""
            desc = ["<enum object at %x: " % id(self)]
            bits = []
            for value, name in self._lookup.items():
                    bits.append("%s: %d" % (name, value))
            desc.append(", ".join(bits))
            desc.append(">")
            return "".join(desc)

</code>

I don't claim that this is the One True Answer but it works for me. It has the 
advantage of going both ways - it can be handy for debugging if you can map 
the value 42 to the name SPAM.

regards,

Tim J (an ex-Delphi programmer :)





More information about the Python-list mailing list