cbs*_*teh 4 python eval list-comprehension python-3.x
考虑以下假设代码:
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()
Run Code Online (Sandbox Code Playgroud)
为什么语句是out1ok 而不是 for out2,这会给出错误“'self' is not defined”?
我正在学习 Python,在试验eval. 是的,我知道eval在这个例子中使用 是不合适的,但只是为了从表面上看这个例子,有人可以解释为什么语句 forout2给出错误信息吗?似乎两个语句都应该起作用并给出相同的结果。
感谢您的任何指导。
通过使用列表理解,您实际上定义了一个新的 scope。事实上,如果我们将列表理解改为:
out2 = [print(globals()) or print(locals()) or eval(cmd) for cmd in ['self.b']]
Run Code Online (Sandbox Code Playgroud)
我们强制 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'}
Run Code Online (Sandbox Code Playgroud)
所以作为局部变量,我们只有 a.0和 a cmd。
但是,您可以self使用以下方法传递到列表理解:
globs = globals()
locs = locals()
out2 = [eval(cmd,globs,locs) for cmd in ['self.b']]Run Code Online (Sandbox Code Playgroud)
所以现在eval(..)将使用在函数作用域中定义的局部和全局变量。由于我们使用locs和globs。Python 会将这些字典的引用传递给eval(..)调用。
最后,每次使用eval(..): eval时都会发出警告,这是一个危险的函数。你最好只在你真的需要它的时候使用它。
该附加范围(在引入额外的副作用蟒-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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1754 次 |
| 最近记录: |