我正在尝试在我的班级内编写字典:
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
如果我这样做:
for element in key:
data[element]=eval("self.%s" %element)
这里没有错误。
怎么回事?
答案 0 :(得分:2)
TL:DR 摘要 -
正如@CoryKramer正确陈述的那样,部分原因是因为字典理解/列表理解/生成器表达式/嵌套函数都在它们自己的范围内进行了评估。但是这个问题的另一半原因是因为使用了eval()
,它在调用它的环境中执行它的表达式,但是它无法访问封闭的命名空间。
或者,我相信你不应该使用eval()
(its pretty dangerous)。要从self
获取属性,您应该使用getattr()
函数 -
data = {element:getattr(self,element) for element in key}
我对那些感兴趣的人的问题的发现 -
部分原因是因为字典理解/列表理解/生成器表达式/嵌套函数都在它们自己的范围内进行计算。但是这个问题的另一半原因是因为使用了eval()
。
eval(expression[, globals[, locals]])
如果省略两个字典,则表达式在调用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>
正如您所见,可以在字典理解中访问self.a
。所以现在让我们检查字典理解的locals()
(本地命名空间)是什么 -
... #same as above, just change the print function call.
print({k:locals() if k < 2 else self.a for k in range(2)})
结果 -
{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}}
可以看出'self'
可以在词典理解中找到(因为它是free variable,这只是因为我直接在词典理解中使用self.a
,如果我没有添加它不会是一个自由变量。让我们解释一下自由变量 -
如果名称绑定在块中,则它是该块的局部变量。如果名称在模块级别绑定,则它是全局变量。 (模块代码块的变量是局部的和全局的。)如果在代码块中使用了变量但在那里没有定义,则它是自由变量。
但是当你使用eval()
来执行表达式时,Python不知道eval()
中使用的任何名称(事先在执行表达式之前),因此它不能绑定{{ 1}}作为一个自由变量来理解。使用self
获取locals()
-
eval
的打印示例
self.a
结果 -
...
print({k:locals() if k < 2 else eval('self.a') for k in range(2)})
因此,当在eval中评估表达式时,它不会在执行的环境中定义{0: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}, 1: {'.0': <range_iterator object at 0x023739B0>, 'k': 1}}
变量。如果你在词典理解中的任何地方使用self
,你就不会得到这个错误 -
self
结果 -
...
print({k:eval('self.a') if k < 2 else self for k in range(2)})
因为然后执行{0: 'Hello', 1: 'Hello'}
表达式的环境知道绑定名称eval
。
使用嵌套函数也可以复制完全相同的问题 -
self
答案 1 :(得分:0)
避免使用 curl -v http://ip-10-0-1-98:7474/db/manage/server/ha/available
[ec2-user@ip-10-0-2-98 log]$ curl -v http://ip-10-0-1-98:7474/db/manage/server/ha/available
* Trying 10.0.1.98...
* Connected to ip-10-0-1-98 (10.0.1.98) port 7474 (#0)
> GET /db/manage/server/ha/available HTTP/1.1
> User-Agent: curl/7.40.0
> Host: ip-10-0-1-98:7474
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Thu, 24 Sep 2015 13:06:52 GMT
< Content-Type: text/plain
< Access-Control-Allow-Origin: *
< Transfer-Encoding: chunked
< Server: Jetty(9.2.4.v20141103)
<
* Connection #0 to host ip-10-0-1-98 left intact
。更好的做法是使用eval
:
getattr