class derived from dict in eval

Alex Martelli aleax at aleax.it
Tue Feb 25 11:48:52 EST 2003


Andrew Dalke wrote:

> Alex:
>> def evalWithSpecialDict(expression, specialDict):
>>     compiled = compile(expression, '<string>', 'eval')
>>     realDict = {}
>>     for varname in compiled.co_names:
>>         realDict[varname] = specialDict[varname]
>>     return eval(compiled, realDict)
> 
> Wow!  Totally different and much cleaner than my code, which looks
> like
> 
> # exception message changes through time
> try:
>   {}["QWE"]
> except KeyError, msg:
>   msg = str(msg)
>   key_start = msg.find("QWE")
>   key_end = -(len(msg) - key_start + 3)

Wow -- heroic, really...

> def super_eval(s, d):
>     real_d = {}
>     while 1:
>         try:
>           return eval(s, real_d)
>         except KeyError, msg:
>           key = str(msg)[key_start:key_end]
>           real_d[key] = d[k]
> 
> (from memory and untested so there may be some mistakes)

Hmmm, one architectural one, I think -- what happens if
d is, say, {'a': 23}, while s is, say, '{}["a"]', which
SHOULD raise a KeyError?  I think this will loop forever...

This can be fixed, e.g. by changing the last statement
to:
            if key in real_d:
                raise
            real_d[key] = d[key]

i.e., if the key IS already in the real_d and yet a
KeyError is still raised, then re-raise it, as it just
can't be fixed.  This idea might come in handy in some
slightly different context.


> I never even thought of compiling the code to look for the list of
> names.  I think I'll rewrite that bit of code now.
> 
> Thanks Alex!

You're welcome!  I'm slightly surprised I didn't already
post this kind code in the past, put it in the cookbook,
or something like that, but some googling suggests I didn't.


Alex





More information about the Python-list mailing list