python中的eval函数范围

Pie*_*olo 20 python eval python-internals

请考虑以下示例:

i=7
j=8
k=10
def test():
    i=1
    j=2
    k=3
    return dict((name,eval(name)) for name in ['i','j','k'])
Run Code Online (Sandbox Code Playgroud)

它返回:

>>> test()
{'i': 7, 'k': 10, 'j': 8}
Run Code Online (Sandbox Code Playgroud)

为什么eval不考虑函数内定义的变量?从文档中,您可以选择传递全局变量和本地字典.这意味着什么?最后,我如何修改这个小案例才能使它工作?

Ash*_*ary 13

生成器实现为函数范围:

类块中定义的名称范围仅限于类块; 它没有扩展到方法的代码块 - 这 包括生成器表达式,因为它们是使用函数作用域实现的.

因此,dict()构造函数中的生成器有自己的locals()字典.现在,让我们来看看Py_eval的源代码,特别是当这两个globals()locals()是无:

if (globals == Py_None) {
        globals = PyEval_GetGlobals();
        if (locals == Py_None)
            locals = PyEval_GetLocals();
    }
Run Code Online (Sandbox Code Playgroud)

因此,对于您的示例PyEval_GetLocals(),在循环执行时globals()将为空,并且将是全局字典.注意i,j并且k在函数内部定义的不在生成器的本地范围内,而是在它的封闭范围内:

>>> dict((name,eval(name, globals(), {})) for name in ['i', 'j', 'k'])
{'i': 7, 'k': 10, 'j': 8}
Run Code Online (Sandbox Code Playgroud)