避免将for循环变量切入Python的全局命名空间的方法

时间:2014-04-29 23:39:07

标签: python for-loop namespaces scope

我想知道是否有办法避免将for循环变量切入Python的全局命名空间?

到目前为止,我能想出的唯一解决方案是使用闭包,例如列表推导

,例如,以下代码:

i = 1
print([i for i in range(5)])
print(i, 'i in global')

j = 1
for j in range(5):
    if j == 4:
        print(j, 'j in for-loop')
print(j, 'j in global')

打印

[0, 1, 2, 3, 4]
1 i in global
4 j in for-loop
4 j in global

编辑:
我假设for循环命名空间属于类别“全局”,与LEGB规则中的函数(“Local”)不同,因此可能没有解决方案吗?顺便说一句,Python 2.x的理解是不是有自己的命名空间?因为在评论中指出Python 2.x会打印“4 in global”(我使用的是Python 3.4)

1 个答案:

答案 0 :(得分:3)

for循环在Python中没有自己的范围;只有周围的范围。因此for表达式中定义的任何变量都将保留在该范围内。它们只是被添加到全局范围内,因为您在函数之外运行代码。如果您将其添加到某个功能中,您会发现它没有"泄漏":

def loop():
    for j in range(5):
        pass

>>> loop()
>>> 'j' in globals()
False

在Python 2.x中,列表推导具有完全相同的行为:它们会将迭代变量添加到局部范围中,因为它们基本上是for构造的语法糖。由于这似乎不断给人们带来惊喜,因此对Python 3.x进行了更改,以便将变量添加到本地范围。

  

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

What's New In Python 3.0

for循环的范围行为对于以下模式非常有用:

# find line number in file with matching text
for i, line in enumerate(some_file):
    if 'some text' in line:
        break
print('First match found at line {}.'.format(i))