我正在将项目从 python 2.7 更新到 python 3.6。
我有一个列表理解,可以从在 python 2.7 中工作的局部变量中查找变量。当我切换到使用全局变量时,它仅适用于 python 3.6。
下面是一个玩具示例来说明这个问题。
相关代码是:
(A,B,C) = (1,2,3)
myvars = ['A','B','C']
如果我执行以下代码:
[locals().get(var) for var in myvars]
python 3.6 中的返回值为:
[None, None, None]
然而,python 2.7中的返回值是:
[1, 2, 3]
如果我使用全局变量执行以下代码:
[globals().get(var) for var in myvars]
然后我在 python 2.7 和 3.6 中得到相同的结果:
[1, 2, 3]
谁能解释为什么使用 locals() 的代码在 python 3.6 中不再有效?
如果我们分解一个更基本的列表理解。我们可以看到为什么会发生这种情况:
>>> 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
那么,上线9
,我们看到 list-comp 实际上创建了一个被调用的函数(在使用生成器时您可能更习惯于此)。因此,该函数将有自己的一组局部变量,因为它位于单独的作用域中 - 从而产生这种意外的行为。
此外,正如指出的@juanpa
, “Python3 的新增功能”文档请明确说明以下内容:
列表推导式具有不同的语义:它们更接近于生成器表达式中的语法糖list()
构造函数,特别是循环控制变量不再泄漏到周围的作用域中。
另请注意,这里有一个错误页面:https://bugs.python.org/issue21161,但是 juanpa 使我相信这不是一个错误,因为它被明确记录为以这种方式工作!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)