[Tutor] eval weirdness
Danny Yoo
dyoo@hkn.eecs.berkeley.edu
Mon Dec 2 03:32:02 2002
> >It appears that the following code causes __builtins__.__dict__ to be
> >assigned to self.names. Can anyone help me understand what is going on
> >here?
> >
> >
> >class testclass:
> > def __init__(self):
> > self.names = {}
> > eval('5 + 5', self.names, self.names)
> > print self.names
> >
> >if __name__ == '__main__':
> > testclass()
Hello Poor Yorick and Gregor!
Wow, this is weird! I never would have expected eval() to touch the
dictionary that we feed in! I'm looking in the C source code at the
eval() function... Yup, it's intentional:
/*** Within bltinmodule.c:builtin_eval ***/
...
if (PyDict_GetItemString(globals, "__builtins__") == NULL) {
if (PyDict_SetItemString(globals, "__builtins__",
PyEval_GetBuiltins()) != 0)
return NULL;
}
...
/******/
... Ah ha! Found the reason. According to:
http://www.faqts.com/knowledge_base/view.phtml/aid/4550/fid/538
the '__builtins__' module is inserted in deliberately so that normal
functions like like int() can still be used.
###
>>> d = {}
>>> eval("int(5.0) + 3", d)
8
>>>
>>> d = {'__builtins__': {}}
>>> eval("int(5.0) + 3", d)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 0, in ?
NameError: name 'int' is not defined
###
Wow, that was a good question. Thank you!
> >>> what = __builtins__.__dict__['help']
> >>> what
> Type help() for interactive help, or help(object) for help about object.
> >>> type(what)
> <type 'instance'>
> >>>
>
> Which class is what an instance of?
The help() 'function' is a little tricky --- it's actually an instance of
a class that's defined within the 'site.py' that runs automatically when
Python starts up:
### within site.py:
class _Helper:
def __repr__(self):
return "Type help() for interactive help, " \
"or help(object) for help about object."
def __call__(self, *args, **kwds):
import pydoc
return pydoc.help(*args, **kwds)
__builtin__.help = _Helper()
###
They've overridden '__repr__', so that when we just type 'help' at the
prompt, it returns that helpful usage message. The implementers have also
overwritten the '__call__' method of help() so that __builtin__.help()
looks like a function, but it's actually a instance in disguise.
I hope this helps!