字典中的Eval函数使用单个引用但不作为字典理解

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

我有一个变量和值列表,我使用eval语句分配给它们。

我试图使用字典理解来匹配变量与评估值。

当我在范围(0,10)中使用for循环时len(ChosenVarNameList)= 10:

 dictinitial = {}
 for i in range (0,len(ChosenVarNameList)):
        dictinitial[ChosenVarNameList[i]] = eval("%s" %ChosenVarNameList[i])

我可以创建字典。

当我引用单个索引时,我也可以看到正确填充的字典(使用下面的代码)。

      dictinitialnew = {ChosenVarNameList[0] : (eval("%s" 
      %ChosenVarNameList[0])).

但是,当我尝试字典理解时,如下面的代码:

 dictinitialnew = {ChosenVarNameList[i] : (eval("%s" %ChosenVarNameList[i])) 
 for i in range (0,len(ChosenVarNameList)) }

我得到代码说第一个变量名称让我们说'Code1'没有定义。有没有办法使用字典理解来做到这一点,或者有一个替代,我必须用来解决这个问题。

提前致谢。

python dictionary
1个回答
1
投票

你的问题是由于dict理解引入了嵌套范围。对于大多数实际目的,dict理解功能如下:

def myfunc(iterable, y):
    return {x: y for x in iterable}

被实现为非常类似于:

def myfunc(iterable, y):
    def _unnamed_func_(_unnamed_it_):
        retval = {}
        for x in _unnamed_it_:
            retval[x] = y  # Note: y is read from nested scope, not passed to inner func
        return retval
    return _unnamed_func_(iterable)  # Note: iterable passed as argument

与所有具有闭包范围的函数一样,_unnamed_func_确定在定义嵌套范围时需要哪些值,并将它们折叠到自己的闭包范围内;在这种情况下,它需要来自嵌套作用域的y,而不是iterable(因为迭代的第一个可迭代作为参数传递给虚函数,而不是通过闭包范围)。

问题是,eval仅在知道本地和全局范围(以及所有代码所具有的内置范围的隐含知识)的情况下执行;它不知道嵌套范围,因为你只通过eval引用变量,嵌套函数也不知道它需要它们。

您可以使用更简单的代码演示一般问题:

def outer(x):
    def inner():
        return eval('x')
    return inner

如果你尝试使用outer(1)()运行(并且在全局范围内没有x),它将与NameError: name 'x' is not defined一起死亡,因为x不是inner关闭范围的一部分,并且当outer返回时它被迅速丢弃。将eval('x')更改为x允许它工作(它在示例中返回1),因为没有eval阻碍,inner在定义时将x拉入其闭合范围,因此当inner稍后运行时它可用。

你的设计是一个糟糕的开始(eval不应该用于阅读简单的变量名称),dict理解只是让它完全打破。

这样做的原因是,理解的语言定义是基于生成器表达式的定义构建的,而生成器表达式必须用闭包范围来实现;因为它们懒惰地运行,如果它们没有使用闭包范围来保持它们依赖于活动的嵌套变量,那么当它们用完时,范围可能不再存在。 Python 2中的list理解用于在没有闭包的情况下执行,但它引起了一些奇怪的工件(例如,在类定义中运行foo = [x for x in y]会给类一个名为x的类属性,其中最终值为x,并且在Python 3中),所有的理解都改为使用隐式闭包范围(这只是listcomps的一个变化;后来添加了dictset的理解,并从一开始就使用了闭包范围)。

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