eval function

Duncan Booth duncan at NOSPAMrcp.co.uk
Thu Apr 24 08:38:20 EDT 2003


Franck Bui-Huu <Franck.BUI-HUU at gemplus.com> wrote in
news:mailman.1051185097.26743.python-list at python.org: 

> but eval seems to not use __getitem__ method of my_dict object because
> "using my_dict" is not printed.
> How can I print "using my_dict" when calling eval function ?

You can't. See http://www.python.org/2.2.2/descrintro.html
"Unifying types and classes in Python 2.2" by Guido van Rossum which
explains: 

> We can also use the new type in contexts where classic only allows
> "real" dictionaries, such as the locals/globals dictionaries for the
> exec statement or the built-in function eval(): 
> 
>     >>> print a.keys()
>     [1, 2]
>     >>> exec "x = 3; print x" in a
>     3
>     >>> print a.keys()
>     ['__builtins__', 1, 2, 'x']
>     >>> print a['x']
>     3
>     >>> 
> 
> However, our __getitem__() method is not used for variable access by
> the interpreter: 
> 
>     >>> exec "print foo" in a
>     Traceback (most recent call last):
>       File "<stdin>", line 1, in ?
>       File "<string>", line 1, in ?
>     NameError: name 'foo' is not defined
>     >>> 
> 
> Why doesn't this print 0.0? The interpreter uses an internal function
> to access the dictionary, which bypasses our __getitem__() override. I
> admit that this can be a problem (although it is only a problem in
> this context, when a dict subclass is used as a locals/globals
> dictionary); it remains to be seen if I can fix this without
> compromising performance in the common case. 

A workaround which might work for you would be to compile the expression 
first (using the 'compile' builtin) and then check the co_names attribute 
of the code object. Then you need to build a real dictionary with just 
those names that can be accessed by the expression. This won't, of course, 
help if your expressions depend on short circuiting logical operators.

>>> c = compile('1+x', '!', 'eval')
>>> c.co_names
('x',)
>>> eval(c, {'x':3})
4
>>> 




-- 
Duncan Booth                                            
duncan at rcp.co.uk int month(char
*p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3" 
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure? 




More information about the Python-list mailing list