[Python-ideas] adopt an enum type for the standard library?
mark at qtrac.eu
Thu Jan 24 09:24:28 CET 2008
On 2008-01-23, Tal Einat wrote:
> Mark Summerfield wrote:
> > On 2008-01-23, Tal Einat wrote:
> > > -1 on adding a specific construct for enums.
> > >
> > >
> > > What I usually do in Python is this:
> > >
> > > ERROR, OK, ALSO_OK = range(-1, -1 + 3)
> > >
> > > Start and stop values, as well step sizes other than one, are easily
> > > achieved. Skipping values is done like this:
> > >
> > > ERROR, OK, ALSO_OK, SOMEOTHER, LAST = range(-1, -1 + 3) + range(1000,
> > > 1000 + 2)
> > >
> > > Updating the range(s) appropriately when adding/changing values is
> > > easy enough. I find this solution to be good enough since the values
> > > are not ever meant to be used explicitly, and values are not
> > > added/changed often.
> > >
> > > This is perhaps not very pretty or concise, but it's simple and it
> > > only uses Python syntax and constructs which everyone knows and
> > > understands. Readability and simplicity are usually my top concerns,
> > > so this fits the bill.
> > Unfortunately, the "const-ness" of enums defined this way is merely
> > conventional, so it is easy to change the value of one by mistake.
> > Using namedtuples means that if you try to assign to the thing you at
> > least get an exception raised. Not that I'm particularly in favour of
> > using namedtuples for this purpose, but they are the only "convenient"
> > way to have enums based on the standard library that I know of.
> (You mean that namedtuples are the only "convenient" way to have
> _"const"_ enums, right?)
> Well, not many things in Python are "const" at all. I didn't realize
> this ("const-ness") was a criterion. So, just to be clear, you want a
> construct which allows setting sequential numerical values to names
> (variables or otherwise), which become "const" from that point
> onwards. Is this correct?
This is the kind of thing I'm looking for:
flags = Enum("OK", "ERROR", "OTHER") # defaults to sequential ints
flags.OK == 0
flags.ERROR == 1
flags.OTHER == 2
flags.OK = 5 # exception raised
flags.FOO # exception raised
str(flags.OK) == "OK"
for flag in flags: # iterates by name
number = flags[flag]
flags == "OTHER"
flags["ERROR"] == 1
flags # exception raised
flags["FOO"] # exception raised
flags = Enum(OK=1, ERROR=-5, OTHER=100)
flags = Enum((("OK", 1), ("OTHER", 100), ("ERROR", -5))) # usful with
It doesn't matter if someone can figure out a way to change an enum
value, so long as assignment doesn't work, to avoid accidental changes.
Could I implement this myself? Yes. So, could any Python programmer.
But that's no use---right now there is no _standard_ way to have enums
in Python. So you either download the PyPI enum package or use one of
those from the Python Cookbook, or write your own. In other words, for
enums we have the Perl-like "there's more than one way to do it". Oh,
and there's one other way, using the standard library:
flags = collections.namedtuple("Enum", "OK ERROR OTHER")(0, 1, 2)
I think enums are a common enough requirement to be worth adding to the
standard library---not to the language.
Mark Summerfield, Qtrac Ltd., www.qtrac.eu
More information about the Python-ideas