
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[2] == "OTHER" flags["ERROR"] == 1 flags[99] # exception raised flags["FOO"] # exception raised other syntaxes: flags = Enum(OK=1, ERROR=-5, OTHER=100) flags = Enum((("OK", 1), ("OTHER", 100), ("ERROR", -5))) # usful with zip() 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