使用列表推导查找变量适用于globals()但不适用于locals().为什么?

dir*_*iel 10 python

我正在将项目从python 2.7更新到python 3.6.

我有一个列表理解,查找在python 2.7中工作的本地变量.当我切换到使用全局变量时,它只适用于python 3.6.

下面是一个说明问题的玩具示例.

相关代码是:

(A,B,C) = (1,2,3)
myvars = ['A','B','C']
Run Code Online (Sandbox Code Playgroud)

如果我执行以下代码:

[locals().get(var) for var in myvars]
Run Code Online (Sandbox Code Playgroud)

python 3.6中的返回值是:

[None, None, None]
Run Code Online (Sandbox Code Playgroud)

但是,python 2.7中的返回值是:

[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

如果我使用globals执行以下代码:

[globals().get(var) for var in myvars]
Run Code Online (Sandbox Code Playgroud)

然后我在python 2.7和3.6中得到相同的结果:

[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释为什么使用locals()的代码不再适用于python 3.6?

Joe*_*don 8

如果我们解释一个更基本的列表理解.我们可以看到为什么会这样:

>>> import dis
>>> dis.dis("[i for i in range(10)]")
  1           0 LOAD_CONST               0 (<code object <listcomp>)
              3 LOAD_CONST               1 ('<listcomp>')
              6 MAKE_FUNCTION            0
              9 LOAD_NAME                0 (range)
             12 LOAD_CONST               2 (10)
             15 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             18 GET_ITER
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             22 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

所以,在线9,我们看到list-comp实际上是一个被调用的函数(在使用生成器时你可能更习惯这个).因此,函数将拥有自己的一组局部变量,因为它位于一个单独的范围内 - 从而产生这种意外行为.


此外,正如所指出的@juanpa,"Python3中的新功能"文档明确说明了以下内容:

列表推导具有不同的语义:它们更接近于list()构造函数内的生成器表达式的语法糖,特别是循环控制变量不再泄漏到周围的范围中.


另请注意,此页面上有一个错误页面:https://bugs.python.org/issue21161,但juanpa已经说服我这不是一个错误,因为它有明确记录以这种方式工作!


che*_*ner 5

列表解析定义在Python 3新的范围,他们并没有在Python 2.做简单的说,A,B,和C是不是在Python 2列表理解局部变量.

顺便说一下,你可能应该一直使用显式的dict {'A': 1, 'B': 2, 'C': 3}而不是单独的变量.现在是解决这个问题的好时机.