递归函数try-except块变量声明异常:两段代码为何表现不同?
嵌套函数与递归中的变量作用域差异解析
先看你给出的代码示例:
可正常运行的嵌套函数代码
class c: def __init__(self, a): self.n=a
def a(): t=c(5) def b(): print(t.n) b()
这段代码能正常打印5,核心原因是嵌套函数的闭包特性:
- 函数
a内部定义了局部变量t,嵌套函数b在a的作用域内被定义,因此b可以捕获并访问a作用域中的t。当调用b()时,直接使用a里已经初始化好的t,自然能正常打印。
无法打印的递归函数代码
def d(): try: t print(t.n) except: t=c(5) d()
这段代码永远不会执行到print(t.n),问题出在递归的栈帧独立性:
- 第一次调用
d()时,进入try块尝试访问t,此时当前栈帧的局部作用域中没有t,触发except块。 - 在当前栈帧里定义
t=c(5)后,递归调用d()——这会创建一个全新的函数栈帧,新栈帧的局部作用域和之前的完全独立,里面并没有t的定义。 - 新的
d()调用又会重复上述过程:try块找不到t,进入except定义t,再递归调用d(),形成无限递归,永远没有栈帧能走到print(t.n)这一步。
两者的核心差异
- 嵌套函数共享外层函数的作用域,
b能直接复用a里的t; - 递归的每次调用都是独立的函数栈帧,每个栈帧的局部变量互不共享,后一次调用无法访问前一次栈帧里定义的
t。
如果要让递归版本正常工作,你需要让t处于所有递归调用的共享作用域,比如用函数默认参数传递:
def d(t=None): if t is None: t=c(5) d(t) else: print(t.n)
这样第一次调用d()时初始化t,递归调用时把t传递下去,就能正常打印5了。
内容的提问来源于stack exchange,提问作者idonthavename
相关产品推荐
相关产品推荐

