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

时间:2016-04-14 07:44:39

标签: python scope eval

我尝试在函数的本地范围内使用eval()。但它始终在全球范围内进行评估。

自包含的例子:

1-此代码有效:

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

2-为NameError

投掷lvar1
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"])

2 个答案:

答案 0 :(得分:4)

保存locals()(或vars())调用的结果以返回函数的本地范围。否则,生成器表达式中的locals()将返回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"])

BTW,字典创建不是必需的:

myDict = locals()  # or vars()

答案 1 :(得分:4)

首先,对read this来说很重要:

  

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

首先要注意,生成器表达式有自己的范围(对于dict-comprehension也是如此),因此它有自己的locals()字典。

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

  2. 在这里,我们再次调用eval(),没有globals()locals() dict,因此最终使用全局范围和自己的本地范围(为空)并在那里在任何这些范围内都没有这样的变量。

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

  4. <强>解决方案:

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