如何实现无Asyncio的Python协程责任链循环?
问题分析与修复方案
核心问题
- 处理器逻辑错误:Handler_59的判断范围与Handler_04重复,未实现5-9区间的处理判断。
- 循环链初始化错误:无法直接构建闭环引用,导致最后一个处理器无法将数据送回第一个。
- 协程终止未处理:处理器
return时会抛出StopIteration,直接send会触发异常。 - 可变默认参数问题:
handler_chain的list=[]会导致多次调用时数据累积。
修复后的实现代码
import functools def coroutine(function): @functools.wraps(function) def wrapper(*args, **kwargs): generator = function(*args, **kwargs) next(generator) return generator return wrapper @coroutine def Handler_04(successor): while True: num = yield if 0 <= num[0] <= 4: print(f"Handler_04 处理数据: {num}") # 处理完成,终止当前协程 return else: try: successor.send(num) except StopIteration: # 后续协程终止,结束当前流程 return @coroutine def Handler_59(successor): while True: num = yield if 5 <= num[0] <= 9: print(f"Handler_59 处理数据: {num}") return else: try: successor.send(num) except StopIteration: return @coroutine def Handler_gt9(successor): while True: num = yield print(f"Handler_gt9 处理数据: {num} → 修改为 [{num[0]-num[1]}, {num[1]}]") num[0] -= num[1] if num[0] < 0: print(f"数据 {num} 无法处理,终止流程") return try: # 修改后送回下一个处理器(即第一个处理器,形成循环) successor.send(num) except StopIteration: return # 构建闭环责任链 # 先创建处理器,后续补全successor引用 first = Handler_04(None) second = Handler_59(None) third = Handler_gt9(first) # 最后一个处理器的下一个是第一个,形成循环 # 补全前两个处理器的successor first.gi_frame.f_locals['successor'] = second second.gi_frame.f_locals['successor'] = third def handler_chain(data_list=None): if data_list is None: data_list = [] for num in data_list: # 复制列表避免原数据被修改 num_copy = num.copy() try: first.send(num_copy) except StopIteration: continue # 测试示例 if __name__ == "__main__": test_data = [[0,5], [5,7], [12,4], [20,6]] handler_chain(test_data)
关键说明
- 闭环链构建:先创建所有处理器,再通过协程的
gi_frame.f_locals修改内部的successor变量,实现Handler_04 → Handler_59 → Handler_gt9 → Handler_04的循环。 - 逻辑修正:Handler_59改为判断5-9区间,每个处理器处理完成后
return终止协程。 - 异常处理:
send时捕获StopIteration,避免后续协程终止时触发全局异常。 - 数据保护:发送数据前复制列表,防止原输入数据被修改。
- 默认参数修复:将
list=[]改为data_list=None,避免可变默认参数的累积问题。
测试输出示例
Handler_04 处理数据: [0, 5] Handler_59 处理数据: [5, 7] Handler_gt9 处理数据: [12, 4] → 修改为 [8, 4] Handler_59 处理数据: [8, 4] Handler_gt9 处理数据: [20, 6] → 修改为 [14, 6] Handler_gt9 处理数据: [14, 6] → 修改为 [8, 6] Handler_59 处理数据: [8, 6]
内容的提问来源于stack exchange,提问作者Maridiama
相关产品推荐
相关产品推荐

