adopt an enum type for the standard library?
AFAIK if you want enumerations you must either create your own, or use a third party module, or use namedtuple: Files = collections.namedtuple("Files", "minimum maximum")(1, 200) ... x = Files.minimum Using: MINIMUM, MAXIMUM = 1, 200 is often inconvenient, since you might have several different ones. Of course you could do: MIN_FILES = 1 MIN_DIRS = 0 Personally, I like enums and consider them to be a fundamental, but I don't like the above approaches. There is an enum module in PyPI http://pypi.python.org/pypi/enum/ and there are several versions in the Python Cookbook. Wouldn't one of these be worth adopting for the standard library? -- Mark Summerfield, Qtrac Ltd., www.qtrac.eu
Mark Summerfield wrote:
There is an enum module in PyPI http://pypi.python.org/pypi/enum/ and there are several versions in the Python Cookbook.
Wouldn't one of these be worth adopting for the standard library?
It might be worth adding an enum to Python 2.6. I'm +0 on it. The enum implementation from pypi is not sufficient for Python core. I don't like its __cmp__ and __hash__ code. I also miss the feature to set a start value or to skip values:
enum = Enum("error=-1", "ok", "also_ok", "someother=1000", "last") enum.error -1 enum.ok 0 enum.also_ok 1 enum.someother 1000 enum.last 1001
Christian
Christian Heimes wrote:
Mark Summerfield wrote:
There is an enum module in PyPI http://pypi.python.org/pypi/enum/ and there are several versions in the Python Cookbook.
Wouldn't one of these be worth adopting for the standard library?
It might be worth adding an enum to Python 2.6. I'm +0 on it.
The enum implementation from pypi is not sufficient for Python core. I don't like its __cmp__ and __hash__ code. I also miss the feature to set a start value or to skip values:
enum = Enum("error=-1", "ok", "also_ok", "someother=1000", "last") enum.error -1 enum.ok 0 enum.also_ok 1 enum.someother 1000 enum.last 1001
Christian
-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. - Tal
On 2008-01-23, Tal Einat wrote:
Christian Heimes wrote:
Mark Summerfield wrote:
There is an enum module in PyPI [snip]
-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. Although I think that enums are a fundamental (as are sets, and yet it took many years for them to arrive in the standard library), at least putting enums in the standard library would allow those who want them to use them out of the box without impinging on those who are happy with not having them. As for which enum implementation, whether the one from PyPI or one from the cookbook, or another one entirely, I have no strong feelings. -- Mark Summerfield, Qtrac Ltd., www.qtrac.eu
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? If that's the case, then I'm still -1. The reason is that, IMHO and AFAIK, having "const" things is un-Pythonic. I think it -great- that I can override anything in Python, even if the original author of the code didn't imagine a reason one would want to do so. - Tal
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
Mark Summerfield schrieb:
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"
I once wrote this: http://twoday.tuwien.ac.at/pub/files/enum I don't know how good this is, though. -panzi
2008/4/12, Mathias Panzenböck <grosser.meister.morti@gmx.net>:
Mark Summerfield schrieb:
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"
I once wrote this: http://twoday.tuwien.ac.at/pub/files/enum
Also: http://norvig.com/python-iaq.html http://www.python.org/doc/essays/metaclasses/Enum.py http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/67107 http://www.faqts.com/knowledge_base/view.phtml/aid/4415
I don't know how good this is, though.
-panzi _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- -- Guilherme H. Polo Goncalves
http://twoday.tuwien.ac.at/pub/files/enum
I don't know how good this is, though.
It's not needed. The namedtuple() function already makes enums trivially simple for anyone who wants to go down this path:
flags = namedtuple('flags', 'OK ERROR OTHER')(*range(3)) flags flags(OK=0, ERROR=1, OTHER=2) flags.OTHER 2
I'm strongly against adding any variant of enum() to the standard library. It distracts users from existing, better approaches like module level constants, classes, dicts, and function attributes. While enums make some sense in compiled languages, there is almost zero need for them in Python. Module level constants are often the way to go -- they look cleaner and they save an unnecessary level of indirection (that is cost-free in a compiled language but expensive in Python): re.IGNORECASE is better than re.flags.IGNORECASE decimal.Overflow is better than decimal.exceptions.Overflow Raymond
On Wed, Jan 23, 2008 at 04:36:26PM +0200, Tal Einat wrote: [...]
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)
are you able to decode that at 4am? :) [...] regards, wrobell <wrobell@pld-linux.org>
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)
Crazy: wheres= Enum() wheres.UP wheres.DOWN wheres.LEFT wheres.close() print UP, DOWN, LEFT, RIGHT 0 1 2 3 Crazier: wheres= Enum() while wheres.open: with wheres: UP, DOWN, LEFT, RIGHT print UP, DOWN, LEFT, RIGHT 0 1 2 3
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)
And yes, there's also: wheres= Enum( UP= 0, DOWN= 0, LEFT= 0, RIGHT= 0 ) print UP, DOWN, LEFT, RIGHT print wheres.UP, wheres.DOWN, wheres.LEFT, wheres.RIGHT 2 0 3 1 2 0 3 1 and: wheres= Enum( 0, 'UP DOWN LEFT RIGHT'.split() ) print UP, DOWN, LEFT, RIGHT print wheres.UP, wheres.DOWN, wheres.LEFT, wheres.RIGHT 0 1 2 3 0 1 2 3
Christian Heimes wrote:
Mark Summerfield wrote:
There is an enum module in PyPI http://pypi.python.org/pypi/enum/ and there are several versions in the Python Cookbook.
Wouldn't one of these be worth adopting for the standard library?
It might be worth adding an enum to Python 2.6. I'm +0 on it.
The enum implementation from pypi is not sufficient for Python core. I don't like its __cmp__ and __hash__ code. I also miss the feature to set a start value or to skip values:
I'd be +1 on adding an enum type. I chose an enum type from the cookbook for our company to use. All was great until 1-2 years later when we needed to start persisting objects that contained enums. We found that that publically available enums wouldn't cope and we had to invest signficant effort in changing our code. E.g. the enum type from pypi:
from enum import Enum import pickle
Colours = Enum('red', 'blue', 'green') x = pickle.dumps(Colours.red) y = pickle.loads(x) print y red assert y == Colours.red Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError
Also, we find that experienced python programmers are use to the absence of a standard enum type but new python programmers are surprised by its absence - it's not 'batteries included'. So I think there would be value in adding an enum to the standard library that does the job correctly.
On Jan 23, 2008 6:59 AM, Mark Summerfield <mark@qtrac.eu> wrote:
Wouldn't one of these be worth adopting for the standard library?
This was rejected before: http://www.python.org/dev/peps/pep-0354/ -- http://www.advogato.org/person/eopadoan/ Bookmarks: http://del.icio.us/edcrypt
On 2008-01-23, Eduardo O. Padoan wrote:
On Jan 23, 2008 6:59 AM, Mark Summerfield <mark@qtrac.eu> wrote:
Wouldn't one of these be worth adopting for the standard library?
This was rejected before: http://www.python.org/dev/peps/pep-0354/
So were set comprehensions, but they're in now... -- Mark Summerfield, Qtrac Ltd., www.qtrac.eu
participants (10)
-
Aaron Brady
-
Christian Heimes
-
Eduardo O. Padoan
-
Guilherme Polo
-
Jonathan Marshall
-
Mark Summerfield
-
Mathias Panzenböck
-
Raymond Hettinger
-
Tal Einat
-
wrobell