Introspection at the module level?

Robert Brewer fumanchu at amor.org
Sun Mar 7 15:58:38 EST 2004


Roy Smith wrote:
> I ended up with:
> 
> map = {}
> for name, value in globals().items():
>         if name.startswith ("OP_"):
>                 map[value] = name
> 
> which seems to work just fine.  Thanks to everybody who 
> responded with suggestions.
> 
> The danger here is that I'm depending on the fact that there are no 
> globals defined elsewhere in the system which start with 
> "OP_", but that 
> seems like a pretty minimal risk.  In fact, it looks like all the 
> externally defined globals are of the form __xxx__.

To help avoid the global collision issue, dump all your OP_ values in a
module-level dictionary or something similar. For a good example, have a
look at the standard library module "htmlentitydefs.py", which should be
included your distribution. It does basically one thing; it provides a
name-to-codepoint dictionary like this:

name2codepoint = {
    'AElig':    0x00c6,
    'Aacute':   0x00c1,
    'Acirc':    0x00c2,
    ...
    'zeta':     0x03b6,
    'zwj':      0x200d,
    'zwnj':     0x200c,
}

...but then goes on to provide a reverse lookup dictionary a la:

# maps the Unicode codepoint to the HTML entity name
codepoint2name = {}

# maps the HTML entity name to the character
# (or a character reference if the character is outside the Latin-1
range)
entitydefs = {}

for (name, codepoint) in name2codepoint.iteritems():
    codepoint2name[codepoint] = name
    if codepoint <= 0xff:
        entitydefs[name] = chr(codepoint)
    else:
        entitydefs[name] = '&#%d;' % codepoint

del name, codepoint


This produces a number of benefits:

1. Keeps the globals() cleaner, and avoids collisions.
2. Makes your iteration code faster, since you're now iterating over a
known, limited set of values, not every possible global.
3. Most importantly, it makes those values more developer-friendly,
since they can now be overridden by consumers. That is, I can't as a
consumer of your code write:

    yourmodule.OP_fish = 'slap'

However, if you place them in a dictionary, I can write:

    yourmodule.OP_vars['fish'] = 'slap'

Even better, of course, would be to place them and their consumers
together in a class, so I could subclass it, but it's far from a perfect
world. ;)


HTH!

Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org




More information about the Python-list mailing list