exec中的python字典理解使用全局变量而不是本地变量

时间:2013-08-03 20:32:24

标签: python python-2.7 exec eval list-comprehension

我发现在exec和eval中使用字典理解和其他方法之间存在以下差异。总之,不同之处在于,当使用理解时,变量取自globals参数,但不使用理解的等效代码从locals参数中获取变量。

这可以从Python Software Foundation Windows安装程序的Python 2.7.3中找到。

执行以下代码时:

locals1 = {"d":{1: 'x', 2: 'y', 3: 'z'}, "test":3}
globals1 = dict(globals().items() + [("d", {1: 'a', 2: 'b', 3: 'c'}), ("test", 2)])
exec "new = {key:d[key] for key in d if key != test}" in globals1, locals1
print locals1

输出结果为:

{'test': 3, 'new': {1: 'a', 3: 'c'}, 'd': {1: 'x', 2: 'y', 3: 'z'}}

请注意,字典(d)和测试值(test)都取自globals参数。

执行等效代码时:

locals2 = {"d":{1: 'x', 2: 'y', 3: 'z'}, "test":3}
globals2 = dict(globals().items() + [("d", {1: 'a', 2: 'b', 3: 'c'}), ("test", 2)])
exec "new = d.copy(); new.pop(test)" in globals2, locals2
print locals2

生成此输出:

{'test': 3, 'new': {1: 'x', 2: 'y'}, 'd': {1: 'x', 2: 'y', 3: 'z'}}

在这种情况下,字典(d)和测试值(测试)都取自locals参数。

进一步的指示是,如果字典和/或测试值不在globals参数中,即使它们在locals参数中,带有理解的代码的执行将失败,并且找不到变量异常。

请注意,这不是关于使用exec的问题,我有充分的理由使用exec。使用eval可以证明相同的情况。

1 个答案:

答案 0 :(得分:1)

这是完全正确的;字典理解作为函数范围执行。在该函数范围中引用的任何变量未定义 ,该范围被假定为全局变量。

如果您在exec代码中使用显式功能,效果会相同:

>>> locals3 = {"d":{1: 'x', 2: 'y', 3: 'z'}, "test":3}
>>> globals3 = dict(globals().items() + [("d", {1: 'a', 2: 'b', 3: 'c'}), ("test", 2)])
>>> exec "def f():\n    new = d.copy()\n    new.pop(test)\n    return new\nnew = f()" in globals3, locals3
>>> print locals3
{'test': 3, 'new': {1: 'a', 3: 'c'}, 'd': {1: 'x', 2: 'y', 3: 'z'}, 'f': <function f at 0x106bbcaa0>}

Displays for sets and dictionaries部分记录了这一点:

  

请注意,理解是在单独的范围内执行的,因此在目标列表中分配的名称不会在封闭范围内“泄漏”。

在Python 2.x中, list comprehensions not 获取自己的范围,这在Python 3中已被更改。