Python: 如何在函数的局部范围内 运行 eval()

Python: How can I run eval() in the local scope of a function

我尝试在函数的局部范围内使用 eval()。但是它总是在全局范围内进行评估。

独立示例:

1- 此代码有效:

var1 = 1
var2 = 2
var3 = 3    
myDict = dict((name, eval(name)) for name in ["var1",
                                              "var2",
                                              "var3"])
print(myDict["var1"])

2- 为 lvar1

抛出 NameError
def test1():
   lvar1 = 1
   lvar2 = 2
   lvar3 = 3
   myDict = dict((name, eval(name)) for name in ["lvar1",
                                                 "lvar2",
                                                 "lvar3"])
   print(myDict["lvar1"])

3- 结果与 2 相同。

def test2():
    lvar1 = 1
    lvar2 = 2
    lvar3 = 3
    myDict = dict((name, eval(name), locals()) for name in ["lvar1",
                                                            "lvar2",
                                                            "lvar3"])
    print(myDict["lvar1"])

locals()(或 vars())调用的结果保存到 return 函数的局部作用域。否则,生成器表达式中的 locals() 将 return gen-expr 的本地范围。

def test3():
    lvar1 = 1
    lvar2 = 2
    lvar3 = 3
    scope = locals()
    myDict = dict((name, eval(name, scope)) for name in [
                  "lvar1", "lvar2", "lvar3"])
    print(myDict["lvar1"])

顺便说一句,您不需要明确的理解来构建该字典:

# copy() avoids quirky, unexpected updates if something else (like a debugger)
# accesses locals() or f_locals
myDict = locals().copy()  # or vars().copy()

首先重要的是 read this:

The expression argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the globals and locals dictionaries as global and local namespace. If the globals dictionary is present and lacks ‘__builtins__’, the current globals are copied into globals before expression is parsed. This means that expression normally has full access to the standard __builtin__ module and restricted environments are propagated. If the locals dictionary is omitted it defaults to the globals dictionary. If both dictionaries are omitted, the expression is executed in the environment where eval() is called. The return value is the result of the evaluated expression`.

首先要注意生成器表达式有自己的作用域(对于字典理解也是如此),因此它有自己的 locals() 字典。

  1. 这是可行的,因为在全局范围内 globals()locals() dict 指向同一个字典,因此 dict 构造函数可以访问这些变量。

  2. 这里我们再次调用 eval() 没有 globals()locals() dict 因此它最终使用全局作用域和它自己的局部作用域(这是空)并且在任何这些范围内都没有这样的变量。

  3. 记住生成器有自己的作用域,所以在这里调用 locals() 几乎没有任何区别,它是一个空字典。

解法:

def test1():
   lvar1 = 1
   lvar2 = 2
   lvar3 = 3
   test1_locals = locals()
   myDict = dict((name, eval(name, test1_locals)) for name in ["lvar1",
                                                 "lvar2",
                                                 "lvar3"])
   print myDict
   print(myDict["lvar1"])

之所以有效,是因为我们在一个变量中捕获了 test1 的 locals(),然后在字典理解中使用了该字典,因此它现在可以访问这些变量。