Ways to avoid that for-loop variables cut into Python's global namespace

╄→гoц情女王★ 提交于 2019-12-08 10:00:33

问题


I am wondering if there is a way to avoid that for-loop variables cut into Python's global namespace?

The only solution I could come up with so far would be using closures, such as list comprehensions

E.g., for the following code:

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')

prints

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

EDIT:
I assume that the for-loop namespace falls into the categoy "Global", unlike a function ("Local") in the LEGB rule, and thus there might be no solution to that? Btw., do Python 2.x comprehensions do not have their own namespace? since it was pointed out in the comments that Python 2.x would print "4 in global" ( I am using Python 3.4)


回答1:


for loops don't have their own scope in Python; there is only surrounding scope. So any variable defined in the for expression will persist in that scope. They're only being added into the global scope because you're running your code outside of a function. If you add it into a function, you'll see it doesn't "leak":

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

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

In Python 2.x, list comprehensions had the exact same behaviour: they would add the iterated variable into the local scope, as they were fundamentally syntactic sugar for the for construct. As this seemed to continually surprise people, it was changed for Python 3.x so that the variables aren't added to the local scope.

Also note that list comprehensions have different semantics: they are closer to syntactic sugar for a generator expression inside a list() constructor, and in particular the loop control variables are no longer leaked into the surrounding scope.

What's New In Python 3.0

The scope behaviour of for loops is useful for patterns like the following:

# 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))


来源:https://stackoverflow.com/questions/23377182/ways-to-avoid-that-for-loop-variables-cut-into-pythons-global-namespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!