[Tutor] parsing chemical formula

Tim Peters tim_one@email.msn.com
Wed, 31 Mar 1999 01:43:38 -0500


>> NAME, NUM, LPAREN, RPAREN, EOS = range(5)

[Christian Tismer]
> 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.

I do believe I was the first to do this, sometime in the first year of
Python's life.  Hard to remember whether Guido was tickled or appalled
<wink>.  Back then you couldn't mix sequence types across an unpacked
assignment, though, so it had to be written with a list on both sides:

[NAME, NUM, LPAREN, RPAREN, EOS] = range(5)

It's nicer now.

While I normally charge hefty royalties for use of this device, I hereby
grant lifetime royalty-free licenses to all readers of the Tutor list
<wink>.

You and Martijn went on to have a lot of fun making count-free variations,
but you neglected to tell the tutorees that anything beyond this is *sick*
fun.  Sick, sick, sick!  This is the way to do it:

import enum
enum.start(100)
import A, B, C, reset500, D, E
enum.stop()
import math
print A, B, C, D, E, math.sqrt(169)  # prints 100 101 102 500 501 13.0

Seriously (and, yes, I'll attach enum.py anyway <wink>), while I generally
oppose by-hand counting too, you have to weigh it against the alternatives,
and anything else here is deadly obscure or deadly clumsy.  Not worth it.  I
usually don't bother to count correctly!  In this idiom, if you get the
count wrong Python will tell you by raising a "unpack of wrong size" error.
Most of the time you guess right; it's not worth any hassle to avoid the few
times you don't.

simple-code-for-our-simple-minds-ly y'rs  - tim


Here's enum.py.  Tutorees, reminder:  this is sick!  Sick, sick, sick.  Do
yourself a favor and don't look at it <wink>.

import __builtin__
_saved_import = __builtin__.__import__
_magic = "reset"
_nmagic = len(_magic)

def _hohoho(name, *args):
    global _base
    if name[:_nmagic] == _magic:
        _base = int(name[_nmagic:])
        return
    this = _base
    _base = _base + 1
    return this

def start(base=1):
    global _base
    _base = base
    __builtin__.__import__ = _hohoho

def stop():
    __builtin__.__import__ = _saved_import