递归函数调用/循环重复异常:Yes/No输入函数迭代次数超预期
解决Yes/No问答函数的递归迭代重复问题
看起来你的问题核心在于递归调用后原循环没有终止,再加上历史决策传递的逻辑有漏洞,导致同一个选项被重复处理,最终生成了多余的布尔值。咱们一步步拆解问题并修复:
问题根源诊断
- 递归后原循环继续执行:当用户输入无效值时,你启动了递归调用,但原函数的
for choice in choices循环并没有停止。递归处理完剩余选项后,原循环会继续推进到下一个选项,直接导致后面的选项被重复提问、重复记录。 - 历史决策传递逻辑错误:你用
for arg in argv: decisions = arg来接收之前的决策记录,但这种写法不仅冗余(每次递归只传一个列表),还容易在多参数场景下覆盖数据,而且没有正确维护列表的引用关系。 choices.index(choice)的潜在风险:如果选项列表里有重复元素,index()会返回第一个匹配项的索引,导致切片后的新列表不符合预期。
优化后的代码(推荐用循环替代递归)
递归在这里反而把流程搞复杂了,换成while True循环处理单个选项的输入,逻辑更清晰,也彻底避免了重复迭代的问题:
def yes_or_no(action, choices, previous_decisions=None): # 初始化历史决策,规避Python可变默认参数的陷阱 decisions = previous_decisions.copy() if previous_decisions is not None else [] for choice in choices: while True: # 预处理输入:去除空格、转小写,提升用户输入容错性 decision = input(f'Do you want to {action} {choice}? Please, type [y/n]: ').strip().lower() if decision == 'y': decisions.append(True) break elif decision == 'n': decisions.append(False) break else: print('\nYour input was neither y = \'yes\' nor n = \'no\'.\nOnce again.') return decisions
关键改进点
- 用循环替代递归:针对单个选项的无效输入,用
while True循环直到用户输入有效值,避免了递归带来的函数调用栈和循环重复问题。 - 安全处理历史决策:用
previous_decisions=None作为默认参数,在函数内部初始化列表,防止Python可变默认参数的意外修改。 - 输入预处理:通过
strip().lower()让用户输入大写Y/N、带空格的输入也能被正确识别,提升体验。
如果你坚持要用递归(不推荐)
如果一定要保留递归逻辑,可以改成每次只处理第一个选项,递归处理剩余列表的方式,确保流程不会重复:
def yes_or_no(action, choices, previous_decisions=None): decisions = previous_decisions.copy() if previous_decisions is not None else [] # 递归终止条件:没有剩余选项时返回结果 if not choices: return decisions current_choice = choices[0] while True: decision = input(f'Do you want to {action} {current_choice}? Please, type [y/n]: ').strip().lower() if decision == 'y': decisions.append(True) break elif decision == 'n': decisions.append(False) break else: print('\nYour input was neither y = \'yes\' nor n = \'no\'.\nOnce again.') # 递归处理剩余选项,直接返回递归结果 return yes_or_no(action, choices[1:], decisions)
测试验证
用你的测试案例运行优化后的代码:
result = yes_or_no('watch', ['football', 'sports']) print(result)
输入流程:
Do you want to watch football? Please, type [y/n]: sure Your input was neither y = 'yes' nor n = 'no'. Once again. Do you want to watch football? Please, type [y/n]: n Do you want to watch sports? Please, type [y/n]: y
返回结果:[False, True],完全符合预期。
内容的提问来源于stack exchange,提问作者anybody
相关产品推荐
相关产品推荐

