Python如何优雅控制用户提问流 支持答案校验与分支跳转逻辑
实现方案
你完全可以沿用字典定义提问流的设计,不需要写大量冗余的if判断,只要给需要校验的问题节点增加校验规则配置即可,整体逻辑依然保持好维护、易扩展的特性。
核心改造思路
- 单独写通用的校验函数,覆盖日期校验、合法选项校验这类重复用到的场景
- 给需要校验的字典节点增加校验相关的配置字段,和原有Y/N类固定选项的跳转逻辑兼容
- 写一套通用的提问主循环,自动根据当前节点的配置决定是直接匹配跳转还是先做输入校验
通用校验函数实现
首先写两个你现在需要用到的校验函数,后续有新的校验需求新增对应函数即可:
from datetime import datetime # 校验输入是否为合法DD/MM/YYYY格式日期 def validate_date(input_str): try: datetime.strptime(input_str.strip(), "%d/%m/%Y") return True except ValueError: return False # 校验输入是否在指定的合法选项列表中 def validate_options(input_str, valid_options): return input_str.strip().upper() in valid_options
改造后的提问流字典
你原来的字典只要微调需要校验的三个节点即可,其余节点完全不用改:
stopquestions = { 'stopconfirm': { 'prompt':'是否要执行该操作? Y/N ', 'Y':'prev', 'N':'genericerror' }, 'prev': { 'prompt':'之前是否完成过? Y/N ', 'Y':'bamerch', 'N':'frequency1' }, 'bamerch': { 'prompt':'操作对象是B还是M? B/M ', 'B':'candate', 'M':'candate' }, 'candate': { 'prompt':'请输入对应日期,格式为DD/MM/YYYY:', 'validator': validate_date, # 绑定日期校验函数 'valid_next': 'length', # 校验通过跳转到的节点 'invalid_next': 'genericerror' # 校验不通过跳转到的节点 }, 'length': { 'prompt':'关于时长的问题是否符合? Y/N ', 'Y':'frequency2', 'N':'frequency2' }, 'frequency1': { 'prompt':'请选择频率:W/F/M/Q/A ', 'validator': lambda x: validate_options(x, ['W','F','M','Q','A']), # 绑定选项校验,指定合法值 'valid_next': 'dis', 'invalid_next': 'genericerror' }, 'frequency2': { 'prompt':'请选择频率:W/F/M/Q/A ', 'validator': lambda x: validate_options(x, ['W','F','M','Q','A']), 'valid_next': 'end', 'invalid_next': 'genericerror' }, 'dis': { 'prompt':'是否与最近的记录存在分歧? Y/N ', 'Y':'end', 'N':'end' }, 'genericerror': { 'text':'输入不合法,请重新进入流程。', 'action':'end' } }
通用提问主循环
这套逻辑写完之后,后续新增问题只要改字典就行,不用动循环逻辑:
def run_question_flow(start_node='stopconfirm'): current_node = start_node answers = {} # 存储所有用户的回答,后续给决策矩阵用 while current_node != 'end': node_config = stopquestions[current_node] # 如果是提示类节点比如错误页,先打印内容再跳转 if 'text' in node_config: print(node_config['text']) current_node = node_config['action'] continue # 提问获取用户输入 user_input = input(node_config['prompt']).strip().upper() answers[current_node] = user_input # 判断当前节点有没有校验器,有就先走校验逻辑 if 'validator' in node_config: if node_config['validator'](user_input): current_node = node_config['valid_next'] else: current_node = node_config['invalid_next'] # 没有校验器的就按原有固定选项匹配跳转 else: current_node = node_config.get(user_input, 'genericerror') print('提问结束,收集到的回答:', answers) # 后续你可以在这里加决策矩阵的逻辑,用answers字典匹配要执行的操作 return answers # 启动提问 if __name__ == '__main__': run_question_flow()
扩展说明
后续如果要加新的校验场景,比如校验手机号、校验数字范围,只要新增对应的校验函数,然后在问题节点里绑定即可,不用修改主逻辑,完全符合你易扩展的需求。
内容的提问来源于stack exchange,提问作者youngstubbs
相关产品推荐
相关产品推荐

