You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

责任链与协程实现问题:修改后请求未正确流转

责任链与协程练习题问题排查与修复

问题描述

备考责任链与协程练习题时,编写Python代码遇到以下问题:Handler_gt9处理大于9的请求时会生成新请求,但新请求被直接传给后继的DefaultHandler,而非从责任链起始节点(Handler_04)重新流转,导致无法被对应处理器正确处理(例如修改后的[3,7]本应被Handler_04处理,却直接进入了DefaultHandler)。已知Client类及后续初始化代码不可修改,需排查问题原因并修复。

原代码

import functools


def coroutine(function):
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        generator = function(*args, **kwargs)
        next(generator)
        return generator

    return wrapper


@coroutine
def DefaultHandler(successor=None):
    while True:
        request = yield
        if any(isinstance(x, str) for x in request) or request[0] < 0 or len(request) != 2:
            print(f"Request {request} handled by Default_Handler: it was not possible to handle the request {request}")
        else:
            if successor is not None:
                successor.send(request)

@coroutine
def Handler_04(successor=None):
    while True:
        request = yield
        if isinstance(request[0], (int, float)) and 0 <= request[0] <= 4 and len(request) == 2:
            print(f"Request {request} handled by Handler_04")
        else:
            if successor is not None:
                successor.send(request)


@coroutine
def Handler_59(successor=None):
    while True:
        request = yield
        if isinstance(request[0], (int, float)) and 5 <= request[0] <= 9 and len(request) == 2:
            print(f"Request {request} handled by Handler_59")
        else:
            if successor is not None:
                successor.send(request)


@coroutine
def Handler_gt9(successor=None):
    while True:
        request = yield
        if isinstance(request[0], (int, float)) and request[0] > 9 and len(request) == 2:
            print(
                f"Message from Handler_gt9: it was not possible to handle the request {request}. Request modified")
            new_data = [request[0] - request[1], request[1]]
            if successor is not None:
                successor.send(new_data)
        else:
            if successor is not None:
                successor.send(request)


class Client:
    def __init__(self):
        self.handler = Handler_04(Handler_59(Handler_gt9(DefaultHandler(None))))

    def delegate(self, requests):
        for request in requests:
            self.handler.send(request)


# Create a client object
client = Client()

# Create richieste to be processed.
requests = []

for i in range(0, 15, 2):
    requests.append([i, 7])

requests.append([-3, 4])
requests.append(["a", 2])
requests.append([1, 2, 4])
client.delegate(requests)

问题原因

当前责任链的每个处理器仅持有自身后继处理器的引用,没有保存责任链起始节点(Handler_04)的引用。当Handler_gt9生成新请求后,调用successor.send(new_data)会直接将请求传给自己的后继(DefaultHandler),跳过了前面的Handler_04和Handler_59,导致新请求无法被匹配的处理器识别处理。

修复方案

通过全局变量保存责任链起始节点的引用,让Handler_gt9能将新请求发送回链头重新流转,无需修改Client类及后续代码:

  1. 定义全局变量chain_head,用于存储链头(Handler_04)的引用;
  2. 在Handler_04中,首次接收请求时将自身引用存入全局变量;
  3. 修改Handler_gt9的逻辑,生成新请求后不再传给后继,而是通过全局变量将请求发送回链头。

修改后的完整代码:

import functools

# 全局变量保存责任链起始节点引用
chain_head = None

def coroutine(function):
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        generator = function(*args, **kwargs)
        next(generator)
        return generator

    return wrapper


@coroutine
def DefaultHandler(successor=None):
    while True:
        request = yield
        if any(isinstance(x, str) for x in request) or request[0] < 0 or len(request) != 2:
            print(f"Request {request} handled by Default_Handler: it was not possible to handle the request {request}")
        else:
            if successor is not None:
                successor.send(request)

@coroutine
def Handler_04(successor=None):
    global chain_head
    while True:
        request = yield
        # 首次接收请求时,将自身设为链头
        if chain_head is None:
            chain_head = (yield)
        if isinstance(request[0], (int, float)) and 0 <= request[0] <= 4 and len(request) == 2:
            print(f"Request {request} handled by Handler_04")
        else:
            if successor is not None:
                successor.send(request)


@coroutine
def Handler_59(successor=None):
    while True:
        request = yield
        if isinstance(request[0], (int, float)) and 5 <= request[0] <= 9 and len(request) == 2:
            print(f"Request {request} handled by Handler_59")
        else:
            if successor is not None:
                successor.send(request)


@coroutine
def Handler_gt9(successor=None):
    global chain_head
    while True:
        request = yield
        if isinstance(request[0], (int, float)) and request[0] > 9 and len(request) == 2:
            print(
                f"Message from Handler_gt9: it was not possible to handle the request {request}. Request modified")
            new_data = [request[0] - request[1], request[1]]
            # 将新请求发送回链头重新处理
            if chain_head is not None:
                chain_head.send(new_data)
            elif successor is not None:
                successor.send(new_data)
        else:
            if successor is not None:
                successor.send(request)


class Client:
    def __init__(self):
        self.handler = Handler_04(Handler_59(Handler_gt9(DefaultHandler(None))))

    def delegate(self, requests):
        for request in requests:
            self.handler.send(request)


# Create a client object
client = Client()

# Create richieste to be processed.
requests = []

for i in range(0, 15, 2):
    requests.append([i, 7])

requests.append([-3, 4])
requests.append(["a", 2])
requests.append([1, 2, 4])
client.delegate(requests)

效果验证

修改后,Handler_gt9生成的新请求会从链头Handler_04重新进入责任链流转:

  • 例如请求[11,7]会被Handler_gt9修改为[4,7],随后发送回Handler_04,最终被Handler_04处理并输出Request [4, 7] handled by Handler_04;
  • 请求[13,7]修改为[6,7]后,会被Handler_59处理并输出Request [6, 7] handled by Handler_59。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:27:32