Python代码执行出现无限循环输出及报错问题求助
问题原因分析与解决方案
这个问题其实是典型的变量覆盖+闭包名字查找规则导致的无限递归,咱们一步步拆解就清楚了:
1. 代码执行的关键流程
先理清楚你的代码在运行时发生了什么:
- 一开始,你定义了两个函数:
foo和parent,此时全局变量parent指向的是那个打印printing from parent function的函数。 - 当执行
parent = foo('hi')时,你把全局变量parent给覆盖了——现在它不再指向原来的parent函数,而是指向foo内部定义的looger函数(顺便提一句,这里你拼写错了,应该是logger,不过不影响问题本质)。 - 接下来调用
parent(),本质是调用looger函数:- 第一行打印
hello from first satatement(这里也有拼写错误,是statement); - 然后执行
parent()——这时候Python会按照LEGB名字查找规则找parent:先找looger的局部作用域(没有),再找foo的闭包外层作用域(也没有),最后找全局作用域的parent。而此时全局的parent已经是looger函数本身了! - 于是就出现了
looger自己调用自己的无限递归——每次递归都会打印第一行的字符串,直到Python的递归深度上限被触发,抛出栈溢出的报错。
- 第一行打印
2. 为什么没调用原来的parent函数?
核心点在于:Python的闭包引用的是变量的名字,而不是变量绑定的具体值。当你用parent = foo('hi')覆盖全局的parent变量后,闭包里的parent指向的就变成了新的函数,而非最初定义的那个parent函数。
3. 修复方案
有两种常见的修复思路:
思路一:在闭包内保存原parent函数的引用
在foo内部先把原来的parent函数存起来,避免被全局变量覆盖影响:
def foo(bar): # 提前保存原parent函数的引用 original_parent = parent def logger(): print('hello from first statement') original_parent() print('hello from second statement') return logger def parent(): print('printing from parent function') # 换个变量名,不要覆盖原parent my_logger = foo('hi') my_logger()
思路二:把parent函数作为参数传入foo
通过参数传递的方式,让闭包直接引用传入的原函数,彻底避免全局变量的干扰:
def foo(bar, parent_func): def logger(): print('hello from first statement') parent_func() print('hello from second statement') return logger def parent(): print('printing from parent function') # 直接把原parent函数作为参数传入 my_logger = foo('hi', parent) my_logger()
内容的提问来源于stack exchange,提问作者Nitin Thakur51
相关产品推荐
相关产品推荐

