第1周·第2讲|一道综合代码推演

下面是纯 Python 示例,字符串列表只是方便观察,不涉及真实模型调用。

复制代码
def prepare(history):
    messages = history
    request = {"messages": messages}

    messages.append("查询订单")
    messages = ["取消订单"]

    return request


def send(request):
    try:
        raise TimeoutError("请求超时")
    except TimeoutError:
        request["messages"].append("超时记录")
        raise


history = ["系统规则"]
request = prepare(history)

try:
    reply = send(request)
    history.append("请求完成")
except TimeoutError:
    history.append("外层已处理")

假设执行前没有定义过 reply。请先不运行,只回答三点:

  1. 最终 history 和 request["messages"] 分别是什么? 为什么有没有"取消订单"?

答:history是"系统规则",request["messages"]是"系统规则","查询订单";因为messages指向的是另一个列表 与request不同

  1. reply 是否获得了值? "请求完成"会不会加入列表?

答:没有 不会

  1. send() 中的 raise 把异常交给了哪里? 为什么最后能执行"外层已处理"?

答:外层函数 try 与 except 因为符合except TimeoutError的情况 舅执行了 "外层已处理"

答:第 2、3 点答对了;第 1 点对"取消订单"的判断正确,但把共享列表的变化漏掉了。 我们按执行顺序把它串起来。

1. 最终两个列表是什么?

history 和 request["messages"] 最终都指向同一个列表:

复制代码
["系统规则", "查询订单", "超时记录", "外层已处理"]

关键在于这两行:

复制代码
messages = history
request = {"messages": messages}

这里没有复制列表。此时三个位置指向同一个对象:

复制代码
history ─────────────┐
messages ────────────┼──→ ["系统规则"]
request["messages"] ─┘

接下来每一步的变化如下:

执行语句 原列表的内容
messages.append("查询订单") ["系统规则", "查询订单"]
messages = ["取消订单"] 不变,只让局部变量 messages 指向新列表
request["messages"].append("超时记录") ["系统规则", "查询订单", "超时记录"]
history.append("外层已处理") ["系统规则", "查询订单", "超时记录", "外层已处理"]

你说的"messages 指向另一个列表"确实成立,但它发生在重新赋值之后,而且没有解除 history 与 request["messages"] 之间的共享关系。

重新赋值后的关系是:

复制代码
history ─────────────┐
                     ├──→ ["系统规则", "查询订单"]
request["messages"] ─┘

messages ───────────────→ ["取消订单"]

所以"取消订单"不会出现在最终结果里。

2. reply 和"请求完成":你的判断正确。

复制代码
reply = send(request)

Python 要先执行右侧调用,正常返回后才会给左侧赋值。send() 抛出了异常,因此:

  • reply 没有获得值;按题设,它仍未定义。
  • 执行流程跳到匹配的 except,跳过 history.append("请求完成")。

3. raise 的去向:你的理解正确。

这里不带参数的 raise 会重新抛出当前正在处理的异常:

复制代码
send() 抛出 TimeoutError
    ↓
send() 内部 except 捕获它
    ↓
追加"超时记录"
    ↓
raise 重新抛出
    ↓
调用处外层 except TimeoutError 捕获
    ↓
追加"外层已处理"

一个措辞修正:这里是"调用处的外层 try/except",示例中这段代码并没有放在另一个函数里。

这次复核已经确认你理解了异常传播、赋值未完成和异常后的语句跳过 。剩下要巩固的是:重新绑定一个变量,不会改变其他变量对原对象的引用;异常也不会自动撤销此前对列表的修改。

相关推荐
ggb喔1 小时前
52pojie 的桌面工具:为什么它们总在高分屏上模糊、资源管理器重启后失效
windows·python·网络安全·软件工程·个人开发·用户界面·用户体验
iCxhust1 小时前
如何批量导出edge保存的密码
前端·windows·edge
JarvanMo1 小时前
写 Flutter 不用再套六层 Widget 了
前端
小羊没烦恼!1 小时前
关于大型asp.net应用系统的架构-架构的选择
java·服务器·开发语言·前端·c#
GISer_Jing1 小时前
height、line-height、font-size相同字体遮挡问题
前端·ai
2301_777998341 小时前
TCP连接断开:进程终止、主机断电与网络断开
linux·服务器·网络·tcp/ip
小羊没烦恼!1 小时前
Windows Azure Platform体验(1):Windows Azure
java·大数据·后端·python·flask·word·.net
字节渡客1 小时前
接口参数偶尔丢失、乱码、解析失败,不是前端传参问题
前端
夏幻灵1 小时前
前端八股:JavaScript 深拷贝详解:实现方式、递归原理与循环引用
开发语言·前端·javascript