Python 在字典理解中使用eval时发生名称错误
我正在尝试在我的类中编写字典:Python 在字典理解中使用eval时发生名称错误,python,class,dictionary,Python,Class,Dictionary,我正在尝试在我的类中编写字典: data = {element:eval("self.%s" %element) for element in key} 我有一个错误: data = {element:eval("self.%s" %element) for element in key} File "<string>", line 1, in <module> NameError: name 'self' is not defin
data = {element:eval("self.%s" %element) for element in key}
我有一个错误:
data = {element:eval("self.%s" %element) for element in key}
File "<string>", line 1, in <module>
NameError: name 'self' is not defined
这里没有错误
为什么会这样?TL:DR总结- 正如@CoryKramer所正确指出的,这部分是因为字典理解/列表理解/生成器表达式/嵌套函数都在各自的范围内求值。但是这个问题的另一半原因是因为使用了
eval()
,它在调用它的环境中执行它的表达式,但是它没有访问封闭名称空间的权限
或者,我认为您不应该使用eval()
()。要从self
获取属性,应使用函数-
data = {element:getattr(self,element) for element in key}
我对这个问题的发现是为那些感兴趣的人准备的- 部分原因是因为字典理解/列表理解/生成器表达式/嵌套函数都在各自的范围内求值。但这个问题的另一半原因是使用了
eval()
如以下文件所示:
eval(表达式[,全局[,局部]])
如果省略了这两个字典,则表达式将在调用eval()的环境中执行。返回值是经过计算的表达式的结果。语法错误报告为异常
(强调矿山)
通常在类中,当您使用字典理解时,您可以在字典理解中使用self
等。范例-
>>> class CA:
... def __init__(self):
... self.a = "Hello"
... print({k:self.a for k in range(2)})
...
>>> CA()
{0: 'Hello', 1: 'Hello'}
<__main__.CA object at 0x008B22D0>
结果-
{0: {'.0': <range_iterator object at 0x02373998>, 'self': <__main__.CA object at 0x008B22D0>, 'k': 1},
1: {'.0': <range_iterator object at 0x02373998>, 'self': <__main__.CA object at 0x008B22D0>, 'k': 1}}
{0: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}, 1: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}}
{0: 'Hello', 1: 'Hello'}
结果-
{0: {'.0': <range_iterator object at 0x02373998>, 'self': <__main__.CA object at 0x008B22D0>, 'k': 1},
1: {'.0': <range_iterator object at 0x02373998>, 'self': <__main__.CA object at 0x008B22D0>, 'k': 1}}
{0: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}, 1: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}}
{0: 'Hello', 1: 'Hello'}
结果-
{0: {'.0': <range_iterator object at 0x02373998>, 'self': <__main__.CA object at 0x008B22D0>, 'k': 1},
1: {'.0': <range_iterator object at 0x02373998>, 'self': <__main__.CA object at 0x008B22D0>, 'k': 1}}
{0: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}, 1: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}}
{0: 'Hello', 1: 'Hello'}
因为执行eval
表达式的环境已经知道名称绑定self
同样的问题也可以使用嵌套函数复制-
>>> def a():
... localb = 10
... def c():
... print(locals())
... print(eval('localb + 20'))
... c()
...
>>> a()
{}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in a
File "<stdin>", line 5, in c
File "<string>", line 1, in <module>
NameError: name 'localb' is not defined
>>定义a():
... localb=10
... def c():
... 打印(局部变量())
... 打印(eval('localb+20'))
... c()
...
>>>()
{}
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第7行,在
文件“”,第5行,c语言
文件“”,第1行,在
NameError:未定义名称“localb”
避免使用eval
。更好的做法是使用getattr
:
data = {element: getattr(self, element) for element in key}
列表理解、dict理解、生成器表达式等都有自己的范围。看,我不认为重复的问题完全回答了这个问题。这与
eval()
也有点相关。为什么要这样做(eval
)?您知道getattr(self,element)
,这会更容易些吗?