Entry
Enumeration (was: Parsing chemical formula)
Mar 9th, 2005 11:56
Martin Miller, Nathan Wallace, Hans Nowak, Snippet 19, Christian Tismer
"""
Packages: basic_applications.enumeration
"""
"""
> > > NAME, NUM, LPAREN, RPAREN, EOS = range(5)
> >
> > As I see this idiom of creating ENUM-alike constants
> > appear again (see doctest), this deserves an entry in
> > some howto. Tim, when did you start using it?
> > Very elegant.
>
> It's a neat idiom. I'm not sure where I got it from (I've used it too),
> but I recall a while back I was pondering the problem. You see, I hate
> counting, and one needs to *count* to do this trick with range. C's
> 'enum' doesn't have this problem. So I tried to figure out an elegant
> way to do something like:
>
> enum(NAME, NUM, LPAREN, RPAREN, EOS)
>
> but couldn't come up with anything that worked well. The main problem is
> of course that NAME etc simply aren't defined, so you get an exception.
> You can catch that exception of course, and then define, but so far
> that's still a kludge.
>
> Perhaps: enum('NAME', 'NUM', 'LPAREN', 'RPAREN', 'EOS') could
> work..still, that is too much typing. :)
>
> Of course this doesn't belong on tutor but in the newsgroup, really, but
> I felt so much mental exertion on my part deserved some mention
> somewhere, and this was a good opportunity. :)
:-))
Well, how 'bout this?
You can even save to type those ugly commas:
"""
def enum(tokens, base=0):
import string
lis = string.split(tokens)
g = globals()
for i in range(len(lis)):
g[lis[i]] = i+base
enum("ONE TWO THREE", 1)
print ONE, TWO, THREE
# (1, 2, 3)
==================
Slight Enhancement:
You can make the above generate identifiers that know their names, which
can be useful when printing or otherwise displaying their values.
class _NamedInt(int):
def __new__(cls, value=0, name=None):
inst = int.__new__(cls, value)
inst.name = name
return inst
def __str__(self): return self.name
__repr__ = __str__
def enum(tokens, base=0):
lst = tokens.split()
gbls = globals()
for i, name in enumerate(lst):
gbls[name] = _NamedInt(i+base, name)
enum("ONE TWO THREE", base=1)
print "print ONE, TWO, THREE:", ONE, TWO, THREE
print "type(ONE):", type(ONE)
print "ONE: str = %s repr = %r" % (ONE, ONE)
print "TWO: str = %s repr = %r" % (TWO, TWO)
print "THREE: str = %s repr = %r" % (THREE, THREE)
print "\nafter assignment 'var = TWO'"
var = TWO
print "var: str = %s repr = %r" % (var, var)
print "var == 2: %r" % (var == 2,)
print "var == TWO: %r" % (var == TWO,)
print "var is TWO: %r" % (var is TWO,)
print "var is 2: %r" % (var is 2,)
print "TWO is 2: %r" % (TWO is 2,)
# print ONE, TWO, THREE: ONE TWO THREE
# type(ONE): <class '__main__.NamedInt'>
# ONE: str = ONE repr = ONE
# TWO: str = TWO repr = TWO
# THREE: str = THREE repr = THREE
#
# after assignment 'var = TWO'
# var: str = TWO repr = TWO
# var == 2: True
# var == TWO: True
# var is TWO: True
# var is 2: False
# TWO is 2: False