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

问题描述 投票:0回答:2

我尝试在函数的局部范围内使用 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"])
python scope eval
2个回答
17
投票

保存

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"])

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

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

7
投票

首先,重要的是阅读本文

表达式参数被解析并计算为 Python 表达式 (从技术上讲,条件列表)使用全局变量和局部变量 字典作为全局和本地命名空间。如果全局字典 存在且缺少

‘__builtins__’
,则复制当前全局变量 在解析表达式之前将其转换为全局变量。这意味着表达式 通常可以完全访问标准
__builtin__
模块并且 传播受限环境。如果本地字典是 省略它默认为全局字典。如果两个字典 被省略,表达式在以下环境中执行 称为
eval()
。返回值是评估的结果 表达`.

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

locals()
字典。

  1. 这是有效的,因为在全局范围内

    globals()
    locals()
    dict 都指向同一个字典,因此 dict 构造函数可以访问这些变量。

  2. 这里我们再次调用

    eval()
    ,没有
    globals()
    locals()
    字典,因此它最终使用全局范围和它自己的本地范围(这是空的),并且在任何这些范围中都没有这样的变量可用.

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

© www.soinside.com 2019 - 2024. All rights reserved.