python - eval 列表理解失败

标签 python python-3.x eval list-comprehension

考虑以下假设代码:

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(..)使用函数范围内定义的局部和全局变量。因为我们使用locsglobs。 Python 将对这些字典的引用传递给 eval(..) 调用。

最后,每次使用 eval(..) 时都会发出警告:eval 是一个危险的函数。您最好仅在确实需要时才使用它。

这个附加作用域的另一个副作用(在 中引入)是循环变量不会泄漏:在列表理解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/

相关文章:

function - 在 dolist 中扩展宏

python - 导入错误 : cannot import name 'network' from 'tensorflow.python.keras.engine'

python - 在 sqlalchemy 中进行自然连接

python-3.x - 无法使用 python-Selenium 单击“提交”按钮

perl - 使用eval加载模块

JavaScript:在其他函数中评估函数

python - 从字典的字典中,返回内部字典的列表,并使用键更新

python扩展模块初始化 - 多个文件

python-3.x - 为 Twisted 中无人维护的 react 堆做出贡献还是维护单独的实现?

Python 递归,为什么我的函数不起作用?