通过使用列表理解,您实际上定义新范围。事实上,如果我们将列表理解更改为:
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
and a cmd
.
不过你可以通过self
使用以下方法进行列表理解:
globs = globals()
locs = locals()
out2 = [eval(cmd,globs,locs) for cmd in ['self.b']]
So now eval(..)
will 使用函数范围内定义的局部变量和全局变量。由于我们使用locs
and globs
。 Python 将对这些字典的引用传递给eval(..)
call.
最后一个警告,就像每次使用一样eval(..)
: eval 是一个危险的函数。您最好仅在确实需要时才使用它。
此附加范围的附加副作用(在python-3.x /questions/tagged/python-3.x)是循环变量 does not泄漏:列表理解之后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