用字典理解和eval()创建一个dict给了我NameError

时间:2015-09-30 19:03:51

标签: python dictionary dictionary-comprehension

我正在尝试以下列方式创建一个包含字典理解的字典(这是一个更大的代码的一部分)

columns = ['zeta', 'Lm', 'u_mean']
print('zeta', eval('zeta'))
print(locals())
dic = {col: [eval(col)] for col in columns}

第一个print完全按预期打印(变量zeta的值),第二个print确认zeta在本地词典中,但在字典理解命令python因此错误而失败

NameError: name 'zeta' is not defined

不幸的是,当尝试重现错误以便在此处发布时,我发现我无法重现错误,因为以下命令在ipython中起作用:

zeta,Lm,u_mean=1,4,69
columns=['zeta', 'Lm', 'u_mean']
print('zeta',eval('zeta'))
print(locals())
dic={ col : [eval(col)] for col in columns }

只有我的代码中的那些命令不起作用。 那么,我错过了什么吗?是否有一些测试可以看到什么是错的?

1 个答案:

答案 0 :(得分:6)

字典理解在新范围中执行,很像嵌套函数调用。您不能指望在列表解析中访问父作用域的本地。

我强烈建议您不要使用这样的本地人。创建一个单独的字典作为命名空间,并在其中查找列:

namespace = {
    'zeta': value_for_zeta,
    # ... etc.
}

然后使用{col: [namespace[col]] for col in columns}

如果不这样做,你可以将locals()字典存储在一个新变量中并引用它;直接或通过将其作为eval()的命名空间传递:

namespace = locals()
dic = {col: [eval(col, namespace)] for col in columns}

或简单地说:

namespace = locals()
dic = {col: [namespace[col]] for col in columns}

现在可以使用,因为namespace闭包;取自父范围的名称。

请注意,相同的限制适用于生成器表达式,集合理解以及Python 3中的列表推导。 Python 2列表推导在所有其他类型之前实现,并遵循不涉及新范围的不同实现策略,但是这种方法不允许生成器表达式工作,并且通常发现具有单独范围的新方法更好地工作