【问题标题】:python dictionary comprehension in exec uses globals instead of localsexec中的python字典理解使用全局变量而不是局部变量
【发布时间】:2013-08-04 21:53:35
【问题描述】:

我发现在 exec 和 eval 中使用字典推导和其他方法之间存在以下差异。总而言之,不同之处在于,使用推导式时,变量取自全局参数,但不使用推导式的等效代码取自本地参数。

这是在 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) 和测试值 (test) 都取自 locals 参数。

进一步的迹象是,如果字典和/或测试值不在 globals 参数中,即使它们在 locals 参数中,使用推导式执行代码将失败并出现变量未找到异常。

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

【问题讨论】:

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


    【解决方案1】:

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

    如果您要在 exec-ed 代码中使用显式函数,您将获得相同的效果:

    >>> 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 推导式没有拥有自己的作用域,这在 Python 3 中已经改变了。

    【讨论】:

      猜你喜欢
      • 2019-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      相关资源
      最近更新 更多