Python嵌套循环变量作用域疑问:为何内层循环会覆盖外层变量?
为什么Python循环变量会被内层循环覆盖?
这是个非常典型的Python作用域问题——没错,Python确实不遵循Java/C那样的块级作用域规则,这也是很多从静态语言转Python的开发者容易踩的坑。
先帮你把代码整理成更易读的格式(你的原始代码因为缩进问题,实际执行结构是这样的):
def temp(): temparray = ['a','b'] temparray_2 = ['c','d','e'] for i in temparray: print('i:' + str(i)) for i in temparray_2: print('first: ' + str(i)) print('Second: ' + str(i)) print('final: ' + str(i))
核心原因:Python没有块级作用域
在Java或C里,每个{}代码块都会创建独立的作用域,循环变量i会被限制在循环块内部,内层循环的i和外层的i是完全不同的变量。但Python的作用域是基于函数、类、模块这三级的,普通的循环、条件判断块(比如for/if)并不会创建新的作用域——也就是说,你在外层循环定义的i,和内层循环用的i是同一个变量!
逐行分析你的输出逻辑
- 进入外层循环,第一次迭代
i = 'a',先输出i:a。 - 进入内层循环,此时
i被重新赋值为temparray_2的元素:- 第一次内层迭代:
i='c',输出first: c - 第二次内层迭代:
i='d',输出first: d - 第三次内层迭代:
i='e',输出first: e
- 第一次内层迭代:
- 内层循环结束,
i的值停留在最后一个元素'e',所以执行print('Second: ' + str(i))时,输出Second: e。 - 外层循环进入第二次迭代,
i被重新赋值为'b',输出i:b。 - 重复内层循环的过程,
i再次被覆盖为'e',输出first: c/first: d/first: e后,执行print('Second: ' + str(i))输出Second: e。 - 外层循环结束,
i的值还是最后一次内层循环的'e',所以最后的print('final: ' + str(i))输出final: e。
怎么避免这种问题?
最简单的办法就是内层循环用不同的变量名,比如把内层的i改成j:
def temp(): temparray = ['a','b'] temparray_2 = ['c','d','e'] for i in temparray: print('i:' + str(i)) for j in temparray_2: print('first: ' + str(j)) print('Second: ' + str(i)) print('final: ' + str(i))
这样内层循环的变量就不会干扰外层的i,输出就符合预期了。
内容的提问来源于stack exchange,提问作者Ted




