Python:如何在函数的本地作用域中运行eval()



我尝试在函数的局部作用域中使用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())调用的结果以返回函数的本地作用域。否则,生成器表达式中的locals()将返回gen表达式的本地作用域。

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()

首先,阅读以下内容很重要:

表达式参数将作为Python表达式进行解析和计算(从技术上讲,是一个条件列表)使用全局和局部字典作为全局和本地命名空间。如果全局字典存在并且缺少‘__builtins__’,则复制当前全局变量在解析表达式之前转换为全局变量。这意味着表达式通常可以完全访问标准__builtin__模块传播受限环境。如果本地字典省略它默认为globals字典。如果两个词典则表达式在以下环境中执行:调用CCD_ 8。返回值是评估的结果表达式`。

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

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

  2. 在这里,我们再次调用没有globals()locals() dict的eval(),因此它最终使用全局作用域和它自己的本地作用域(它是空的),并且在这些作用域中都没有可用的此类变量。

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

解决方案:

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(),然后在字典理解中使用了该字典,所以它现在可以访问这些变量。

最新更新