class derived from dict in eval
Alex Martelli
aleax at aleax.it
Sat Mar 1 02:04:51 EST 2003
Aahz wrote:
> In article <nNw6a.308773$AA2.11749597 at news2.tin.it>,
> Alex Martelli <aleax at aleax.it> wrote:
>>
>>You have to prepare a real dictionary for the names used
>>in the expression you're interested in, because, as others
>>said responding to you, the LOAD_NAME operation bypasses
>>polymorphic behavior and goes for actual dict item access.
>>
>>Fortunately, it's not too hard:
>>
>>def evalWithSpecialDict(expression, specialDict):
>> compiled = compile(expression, '<string>', 'eval')
>> realDict = {}
>> for varname in compiled.co_names:
>> realDict[varname] = specialDict[varname]
>> return eval(compiled, realDict)
>
> You're sick. You need help.
Hmmm, I guess I'll take that as a compliment. However, as
Andrew pointed out, this doesn't work right if the expression
can include qualified names, e.g. an expression strings of
"foo.bar"
will have TWO items in co_names -- 'foo' _and_ 'bar'. This
means the above code won't work right -- consider:
class foo:
bar=23
def __getitem__(self, name):
if name=='foo': return self
raise KeyError
evalWithSpecialDict('foo.bar', foo())
this will die with a KeyError when trying to access
key 'bar' in the mapping, unnecessarily. So at the very
least we need to ignore this kind of things:
def betterEval(expression, specialDict):
compiled = compile(expression, '<string>', 'eval')
realDict = {}
for varname in compiled.co_names:
try: realDict[varname] = specialDict[varname]
except KeyError: pass
return eval(compiled, realDict)
As Andrew also noticed, this is still imperfect in
some cases, i.e., consider:
class foo:
bar=23
def __getitem__(self, name):
if name=='foo':
return self
elif name=='bar':
time.sleep(10800)
return 999
raise KeyError
Now, betterEval('foo.bar', foo()) does succeed, but
it wastes 3 hours of elapsed time it wouldn't need,
because it asks foo() for the toplevel name 'bar'
which it doesn't really need.
So, I _did_ get help, and enhanced this approach, but
for the case of expressions that use qualified names,
and mappings that may take a lot of computational
effort to produce the values for some of their keys,
it's hard to see how to make things satisfactory...
Alex
More information about the Python-list
mailing list