考虑以下假设代码:
class B(object):
def __init__(self):
self.b = 2
def foo(self):
out1 = [eval('self.b')] # ok
print(out1) # prints: [2]
out2 = [eval(cmd) for cmd in ['self.b']] # fails
print(out2) # NameError: name 'self' is not defined
b = B()
b.foo()
为什么声明是out1
好的,但不适用于 out2
,这会给出错误“'self'未定义”?
我正在学习Python,我在尝试eval
时遇到了这个问题。 。是的,我知道 eval
的用途在这个例子中是不合适的,但只是为了从表面上看这个例子,有人可以解释为什么 out2
的声明给出错误信息?看来这两个语句应该有效并给出相同的结果。
感谢您的指导。
最佳答案
通过使用列表理解,您实际上定义了一个新范围。事实上,如果我们将列表理解更改为:
out2 = [print(globals()) or print(locals()) or eval(cmd) for cmd in ['self.b']]
我们强制 Python 在调用 eval(..)
之前打印局部变量和全局变量,我们得到如下内容:
{'__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'b': <__main__.B object at 0x7f406f55d4a8>, '__doc__': None, '__package__': None, 'B': <class '__main__.B'>, '__spec__': None}
{'.0': <list_iterator object at 0x7f406f55df28>, 'cmd': 'self.b'}
因此,作为局部变量,我们只有一个 .0
和一个 cmd
。
但是,您可以使用以下方法将 self
传递给列表理解:
<b>globs = globals()</b>
<b>locs = locals()</b>
out2 = [eval(cmd<b>,globs,locs</b>) for cmd in ['self.b']]
所以现在eval(..)
将使用函数范围内定义的局部和全局变量。因为我们使用locs
和globs
。 Python 将对这些字典的引用传递给 eval(..)
调用。
最后,每次使用 eval(..)
时都会发出警告:eval 是一个危险的函数。您最好仅在确实需要时才使用它。
这个附加作用域的另一个副作用(在 python-3.x 中引入)是循环变量不会泄漏:在列表理解cmd<之后
已清理:您无法再访问它(通常它会保存它处理的最后一个元素)。例如:
>>> [x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
关于python - eval 列表理解失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45194934/