news 2026/10/15 13:35:43

Python 列表、字典与 JSON:用聊天消息搞懂取值、清理和参数传递

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 列表、字典与 JSON:用聊天消息搞懂取值、清理和参数传递

摘要:围绕一组聊天消息,讲清列表与字典的嵌套取值、get()的默认值、for遍历、strip()清理、JSON 字符串与文件读写,以及*、**参数拆包。重点不是背方法名,而是判断当前数据是什么类型、代码执行后数据发生了什么变化。

所属专栏:大模型应用开发的 Python 工程基础 · 第 2 篇
适合读者:已了解变量、函数参数与返回值,但容易混淆列表、字典和 JSON 字符串的 Python 初学者。
运行环境:Python 3.10+,仅使用标准库。第一节和文件读写示例可以独立运行;其余片段说明各自需要的数据,不要把错误示例一起粘贴执行。

写聊天接口、处理模型消息或读取工具参数时,经常会看到这样的代码:

data["messages"][0]["content"]

它看起来很长,其实只是逐层取值。本篇先处理一组聊天消息,再围绕这条流程拆解常用操作。不涉及模型调用、数据库或框架,让注意力集中在 Python 数据本身。

一、贯穿示例:读消息、清理内容、转回 JSON

假设收到一段 JSON 文本,需要读取每条消息,并清理内容两端的空白。

importjson# Python 自带的 JSON 模块,不需要额外安装。# 三个双引号用于书写多行字符串;raw 此时仍然是文本。raw=""" { "messages": [ {"role": "user", "content": " 你好 "}, {"role": "assistant", "content": " 有什么可以帮助你? "} ] } """data=json.loads(raw)# 解析 JSON;本例最外层是对象,结果是字典。messages=data["messages"]# 按键取出消息列表。formessageinmessages:# 每次取出一个消息字典,再执行缩进内的代码。message["content"]=message["content"].strip()# 清理并写回当前字典。first_content=messages[0]["content"]# 下标 0 表示第一个元素。request_id=data.get("request_id","未提供")# 缺少这个键时使用默认值。result=json.dumps(data,ensure_ascii=False)# 转为 JSON 字符串,保留中文显示。print(first_content)print(request_id)print(result)

预期输出:

你好 未提供 {"messages": [{"role": "user", "content": "你好"}, {"role": "assistant", "content": "有什么可以帮助你?"}]}

这段代码没有调用模型,也没有写文件。它完成的是:文本解析、读取数据、修改内容、再生成文本。

二、判断类型:看当前这一层,不要被里面的内容带偏

解析后的数据结构是:

data={"messages":[{"role":"user","content":"你好"},{"role":"assistant","content":"有什么可以帮助你?"},]}

虽然里面有列表,但data本身是字典。沿着取值过程看:

表达式本例中的类型含义
data字典整份数据,最外层是键值结构
data["messages"]列表所有消息,按顺序保存
data["messages"][0]字典第一条消息,有角色和内容两个字段
data["messages"][0]["content"]字符串第一条消息的具体文字,即"你好"

方括号在这里有两种用途:字典用键取值,列表用位置取元素。位置从 0 开始;列表为空时,不能直接取[0],否则会发生索引错误。

阅读嵌套数据的诀窍是:每取一层,就重新判断手里拿到的是什么。

不要只看到其中的[]就认定整份数据是列表,也不要认为json.loads()永远返回字典:JSON 对象通常解析成字典,JSON 数组解析成列表,其他 JSON 值也有各自对应的 Python 类型。

三、字典 get():缺键、None 和空字符串是三种情况

data={"message":"你好"}message=data["message"]# 已知键存在时,直接读取。request_id=data.get("request_id")# 没有这个键,返回 None。request_id=data.get("request_id","未提供")# 没有这个键,返回指定默认值。

get()是字典自带的方法。第二个参数的含义是“键不存在时使用的值”,不是“内容为空时使用的值”。

字典内容data.get("request_id", "未提供")的结果
{}"未提供"
{"request_id": None}None
{"request_id": ""}空字符串""

没有传入默认值时,缺键默认返回None。参考:Python 官方字典方法

如果写data["request_id"]而键不存在,会抛出KeyError。不能简单地认为get()永远更好:可选字段可以缺失;必填字段缺失则需要明确检查和报错,不能用默认值悄悄掩盖。

四、遍历与清理:同样的处理,应用到每条消息

4.1 for 每次取出的是元素,不是序号

使用第一节中的messages列表:

formessageinmessages:print(message["role"],message["content"])

第一次循环,message接收第一条消息字典;第二次接收第二条。每次执行相同的缩进代码,元素取完后循环结束。

message是自己起的变量名,不是 Python 固定要求的名字,也不是下标。这样写能处理不同数量的消息,不必手动写很多次messages[0]、messages[1]。

4.2 strip() 清理两端,并返回清理后的字符串

text=" hello world \n"clean_text=text.strip()print(clean_text)# hello world,中间的空格保留。

默认的strip()去掉字符串两端的空白,包括空格、换行和制表符等;不删除中间的空格。参考:Python 官方字符串方法

最常见的错误是没有保存返回值:

text=" 你好 "text.strip()# 计算了结果,但没有接住;text 的内容不变。text=text.strip()# 保存清理结果,text 现在是 "你好"。

strip()不会原地修改字符串。要修改消息字典中的字段,就把返回的字符串写回去:

# message 是当前循环取出的消息字典。message["content"]=message["content"].strip()

在本文的普通列表遍历中,当前字典没有被复制,因此修改它,也会改变列表中对应的那条消息。这与上一篇“变量引用同一个对象”的理解相衔接。

业务上还要注意:只含空白的输入清理后会变成""。清理完成,不等于内容有效。代码、缩进文本等场景也不能不加判断地去掉两端空白,是否清理要看字段用途。

五、JSON 的四个方法:先问“字符串还是文件”

5.1 loads 与 dumps:处理字符串

importjson raw='{"message": "你好"}'# JSON 字符串。data=json.loads(raw)# 本例解析结果是字典。result=json.dumps(data,ensure_ascii=False)# 返回 JSON 字符串。print(data["message"])# 你好print(result)# {"message": "你好"}

最外层包住整段内容的引号很重要:'{"message": "你好"}'是字符串,{"message": "你好"}是 Python 字典。

print(result)看起来像在显示字典,并不代表result是字典。打印字符串时,不会额外显示包住整个字符串的引号;要按键读取它,需要先解析。

ensure_ascii=False让中文直接显示,而不是转换成\uXXXX形式;必要的 JSON 转义仍然保留。它不是文件编码配置,文件编码要在打开文件时指定。

已经是字典的数据不需要再次loads()。JSON 的键需要双引号;"{'message': '你好'}"虽然像 Python 字典的文本表示,但不是合法 JSON 文本,不能直接交给loads()。

5.2 load 与 dump:读取或写入文件对象

下面是独立示例。若实际运行,会在当前工作目录创建message_demo.json;文件已经存在时会报错,不会覆盖。

importjson data={"message":"你好"}# open() 打开文件;"x" 创建新文件,已存在就报错。# encoding="utf-8" 指定文件编码。# with ... as file 把文件对象交给 file,代码块结束后自动关闭。withopen("message_demo.json","x",encoding="utf-8")asfile:json.dump(data,file,ensure_ascii=False)# 将 JSON 写入文件。# "r" 表示读取文件。withopen("message_demo.json","r",encoding="utf-8")asfile:restored=json.load(file)# 读取 JSON 并解析成 Python 数据。print(restored["message"])# 预期输出:你好。

本节只使用with自动关闭文件,不展开资源管理机制。注意传给load()的是文件对象,不是文件名:json.load("message_demo.json")不符合这个接口的要求。

四个方法可以这样选:参考:Python 官方 JSON 文档

方法接收什么结果或作用
json.loads(raw)JSON 字符串;也支持 JSON 字节数据解析成对应的 Python 数据
json.dumps(data)可进行 JSON 编码的 Python 数据返回 JSON 字符串
json.load(file)支持读取的文件对象读取并解析 JSON
json.dump(data, file)数据和支持写入的文本文件对象将 JSON 写入文件,成功后返回None

初学时可以记为:load读进来,dump写出去;带s的主要用于字符串形式。只在下一个环节需要不同形式时转换,不要反复把字典转成文本、再转回字典。

六、参数拆包:按名字传,还是按顺序传?

我们自己定义一个构造消息字典的函数,它不是 Python 或某个 SDK 自带的接口:

defcreate_message(content,role="user"):# content 必填;role 不传时使用默认值 "user"。return{"role":role,"content":content}

6.1**字典:按键名传入参数

定义上面的函数后,可以这样调用:

data={"role":"user","content":"你好"}message=create_message(**data)# 等价于 create_message(role="user", content="你好")。

**data将字典的键作为参数名、值作为参数值。对于本例,字典里两个键的先后顺序不影响对应关系。

不是“参数数量必须和字典键数一样”,而是:必填参数不能缺,带默认值的可以不传,提供的名字必须是函数接受的名字。

data={"content":"你好"}message=create_message(**data)# role 没有提供,使用默认值 "user"。

对于这个没有接收额外关键字参数的普通函数,键改成text或多传request_id都会报错。Python 不会猜测text就是content。

6.2*列表:按位置依次传入参数

仍然使用本节开头的函数:

values=["你好","user"]message=create_message(*values)# 等价于 create_message("你好", "user")。# 第一个值传给 content,第二个值传给 role。

*不只用于元组,也可以拆开列表等可迭代对象。本文先掌握列表这个常见情况即可。参考:Python 官方参数拆包教程

顺序反了,可能不报错,但业务含义会错:

values=["user","你好"]message=create_message(*values)print(message)# {'role': '你好', 'content': 'user'}

该函数没有检查角色是否合法,只会按参数位置接收。角色、内容这种有明确含义的字段,按名称传参通常更容易审查。

*、**是调用时的传参方式,不是 JSON 解析,也不会替你完成业务校验。不要把未经检查的外部大字典直接拆包给任意函数。

七、常见错误对照

表现错误思路或写法正确判断
想按键取值,却把数据当成了列表看到内部有[],认定整个data是列表看当前层;本文最外层是字典
缺键时报错对可缺失字段直接用data["request_id"]根据业务使用get()或明确校验
默认值没有生效认为键的值为None或""时会使用默认值get()的默认值只在缺键时使用
内容两端的空格还在调用strip()但不保存返回值保存结果或写回字段
JSON 解析失败把 Python 字典的单引号文本当作 JSON使用合法 JSON,或对已有字典直接操作
把写文件结果当成文本用result = json.dump(...)获取 JSON 字符串需要字符串时使用dumps()
拆包传参报错字典的键不符合函数参数要求必填、默认值和接收的名字一起检查
函数执行成功但内容错了*列表的元素顺序反了按位置核对,必要时改为按名称传参

八、综合练习与验收

使用第一节的完整示例,先手动判断,再在方便时运行:

  1. data、messages、result分别是什么类型?
  2. first_content和request_id分别是什么?
  3. 如果循环内只写message["content"].strip(),原字典的内容会改变吗?
  4. 如果直接把data写入已经打开的文件,选择dump()还是dumps()?
  5. 调用create_message(**{"content": "你好"})时,为什么缺少role仍然可以执行?

参考答案:

  • 第 1 题:字典、列表、字符串。每个变量的类型由它当前接收的数据决定。
  • 第 2 题:"你好"和"未提供"。
  • 第 3 题:不会。清理结果没有写回。
  • 第 4 题:dump(),接收数据和文件对象。
  • 第 5 题:role有默认值;缺少必填的content则不能这样调用。

验收不是背出方法名称,而是能解释每一步拿到什么、修改了哪里,以及参数为什么能对应。手动回答通过说明概念与代码阅读理解;实际动手还要验证正确示例,并能修复错误案例。

九、总结

处理数据时,先判断类型,再选择操作。列表按位置组织元素,字典按键组织字段;嵌套结构需要逐层判断。get()处理缺键,strip()返回清理后的字符串,JSON 方法根据“文本还是文件”选择,参数拆包则区分“按位置”和“按名称”。

先把这条小流程读懂,后续处理请求、聊天历史和工具参数时,才不容易把文本、字典、列表和函数参数混在一起。

你最容易混淆的是嵌套取值,还是 JSON 的四个方法?欢迎在评论区交流你的判断过程。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 13:35:37

078、绑定信息存储与重连时密钥恢复异常

上个月帮一个做物联网网关的团队排查问题,他们的设备在运行两三天后,只要网络闪断一次,就再也连不上平台了。现场日志只留下一句“密钥恢复失败”,然后设备反复重试,直到看门狗复位。复位之后正常,过两天又…

作者头像 李华
网站建设 2026/10/15 13:35:12

图转PPT怎么做?把截图一键还原成可编辑PPT的实测

周三晚上十点,项目群突然弹出一张截图——上一版汇报PPT的完整页面,领导只说了一句:"数据换成最新的,明天上午要用。"盯着那张图,你会发现一个尴尬的事实:图里的字选不中,表格点不开&…

作者头像 李华
网站建设 2026/10/15 13:35:03

ASP.NET Identity身份认证系统设计与实践

1. 项目概述:身份认证系统的演进之路十年前我接手第一个企业级会员系统时,还在用FormsAuthentication手动管理用户票据。如今在.NET生态中,ASP.NET Identity已经成为了现代化身份管理的标准解决方案。这个演变过程不仅仅是技术组件的更替&…

作者头像 李华
网站建设 2026/10/15 13:35:03

Windows Terminal深度配置指南:从安装到生产级定制

1. 为什么现在必须认真对待 Windows Terminal —— 它早已不是“又一个命令行窗口”Windows Terminal 这个名字听起来平平无奇,就像“记事本”或“画图”一样,容易被当成系统自带、凑合能用的附属品。但如果你还在用 CMD 或 PowerShell 的传统控制台窗口…

作者头像 李华
网站建设 2026/10/15 13:33:58

Android嵌套滚动冲突解决方案:RecyclerView与ScrollView

1. 问题背景与现象拆解在Android应用开发中,RecyclerView与ScrollView的嵌套组合堪称"经典坑位"。当我们需要在纵向滚动的ScrollView内部嵌入一个同样支持纵向滚动的RecyclerView时,手指滑动操作会变得异常诡异——要么只有外层ScrollView响应…

作者头像 李华