Python递归中nonlocal变量flag的异常行为求助
问题分析:Python中
or短路求值对nonlocal变量的影响 原代码与问题现象
原期望在3次调用recur()后,nonlocal变量flag保持为True,但实际运行后flag最终变回False:
def f(): flag = False def recur(n): nonlocal flag print(f"this is recur {n}") print("flag is: ", flag) if n == 2: print(f"end of recur {n}") print("flag is: ", flag) return True flag = flag or recur(n+1) # 问题代码行 print(f"end of recur {n}") print("flag is: ", flag) return False recur(0) f()
运行输出:
this is recur 0 flag is: False this is recur 1 flag is: False this is recur 2 flag is: False end of recur 2 flag is: False end of recur 1 flag is: True end of recur 0 flag is: False <-- 预期此处为True
将问题代码行改为flag = recur(n+1) or flag后,输出符合预期,flag最终保持True。
原因解析:or的短路求值规则
Python中or运算符遵循短路求值逻辑:
- 当左侧表达式为真时,直接返回左侧结果,不会执行右侧表达式
- 当左侧表达式为假时,才会执行右侧表达式,返回右侧结果
原代码执行流程拆解
- 调用
recur(0):此时flag为False,执行flag = False or recur(1),左侧为False,因此执行recur(1) - 调用
recur(1):flag仍为False,执行flag = False or recur(2),左侧为False,因此执行recur(2) - 调用
recur(2):触发n==2条件,返回True - 回到
recur(1):recur(2)返回True,False or True结果为True,flag被设为True,随后recur(1)返回False - 回到
recur(0):执行flag = False or recur(1),而recur(1)返回的是False,False or False结果为False,flag被重新设为False——这就是问题根源!
修改后代码的执行流程
当改为flag = recur(n+1) or flag:
- 调用
recur(0):执行flag = recur(1) or False,先执行recur(1) - 调用
recur(1):执行flag = recur(2) or False,先执行recur(2) - 调用
recur(2):返回True - 回到
recur(1):recur(2)返回True,触发or的短路求值,直接返回True,flag被设为True,随后recur(1)返回False - 回到
recur(0):recur(1)返回False,执行False or flag,此时flag已经被recur(1)设为True,最终flag保持为True
总结
问题核心是or的短路顺序差异:
- 原代码中,
flag or recur(n+1)先判断当前flag,递归返回的结果仅在当前flag为False时赋值,但递归函数本身返回False,导致上层递归会把flag重新覆盖为False - 修改后的
recur(n+1) or flag先执行递归,递归过程中已将flag设为True,后续即使上层递归返回False,or的右侧是已为True的flag,最终不会改变flag的真值
内容的提问来源于stack exchange,提问作者stackUnderflow
相关产品推荐
相关产品推荐

