我很难理解eval()
在评估表达式中使用的全局变量的行为方式。
例如,以下脚本打印1
:
x = 1
print eval('x')
以下脚本在NameError: name 'x' is not defined
上失败:
x = 1
print eval('x', {})
然而,从the documentation of eval()
for my Python version(强调我的):
表达式参数使用 globals 和 locals 字典作为Python表达式(技术上讲,条件列表)进行解析和评估。全局和本地命名空间。 如果 globals 字典存在且缺少'__builtins__',则在解析表达式之前将当前全局变量复制到 globals
所以根据这个,由于 globals 参数存在且确实缺少__builtins__
,我希望所有当前的全局变量 - 包括x
- 都是在评估表达式之前将其复制到其中;但显然事实并非如此。我错过了什么?
答案 0 :(得分:4)
这似乎是一个错误。无论是文档中的错误还是实现中的错误,我都不知道,但eval
如果globals
不存在,则不会将当前全局变量复制到__builtins__
。相反,it only copies __builtins__
:
if (PyDict_GetItemString(globals, "__builtins__") == NULL) {
if (PyDict_SetItemString(globals, "__builtins__",
PyEval_GetBuiltins()) != 0)
return NULL;
}
我在Python bug tracker上没有找到任何关于此内容的信息,并且差异仍然存在于3.4和当前的开发分支中,因此可能值得提交错误报告和建议的文档更正:
如果 globals 字典存在且缺少“
__builtins__
”,则在表达式<之前将当前__builtins__
复制到 globals 中/ em>被解析。