订单不是一行扁平的数据:它有明细,每条明细还有加料。想一步跳到底,KeyError 就是这么来的。应该先检查哪一层?
真实数据很少能塞进一个列表或字典里。订单包含商品,接口响应包含对象,记录包含字段。给每一层命名,并一次只访问一层,嵌套数据就会清楚很多。 你还会逐层校验、把嵌套记录摊平成行,并用显式栈遍历树。
字典组成的列表
外层列表保存多条记录,每个字典保存一条记录的字段。遍历列表,再从每个字典里读取键。很多 JSON 文件都是这种形状。
orders = [
{"drink": "latte", "price": 4.5},
{"drink": "tea", "price": 3.0},
]
for order in orders:
print(order["drink"], order["price"])列表中的记录
读取嵌套键
每一层用一对方括号。data["shop"] 返回内层字典,再用 ["name"] 读取字段。路径变长时,可以先把中间结果存进变量。
data = {"shop": {"name": "Corner", "open": True}}
print(data["shop"]["name"])
print(data["shop"]["open"])两层键
更新字段并计算总和
嵌套值仍然是普通的字典值,所以赋值方式不变。要对某个字段求和,就遍历外层列表,从每条记录里读取该键。能用循环表达意图时,不要硬编码索引。
orders = [{"price": 3.0}, {"price": 4.5}]
orders[0]["price"] = 3.5
total = sum(order["price"] for order in orders)
print(total)更新并求和
每一层都要校验
嵌套读取是一串假设。每一层都检查容器类型和键,或者先用 get() 给空默认值再索引。在边界做一次校验,比从三个地方分别接住 TypeError 和 KeyError 便宜。
payload = {"shop": {"name": "Corner", "orders": [{"total": 9.0}]}}
shop = payload.get("shop", {})
orders = shop.get("orders", []) if isinstance(shop, dict) else []
first_total = orders[0].get("total") if orders and isinstance(orders[0], dict) else None
print(shop.get("name", "unknown"))
print(first_total)
print(payload.get("missing", {}).get("name", "unknown"))先检查容器,再读键
把嵌套记录摊平成行
嵌套订单适合存储,却不适合直接汇报。一次摊平一层:外层订单、内层商品,再生成同时带两个标识的行。缺失值要显式保留,不要悄悄丢掉整行。
orders = [
{"id": 1, "items": [{"name": "latte", "qty": 2}]},
{"id": 2, "items": [{"name": "tea", "qty": 1}, {"name": "mocha", "qty": 3}]},
]
rows = []
for order in orders:
for item in order.get("items", []):
rows.append((order["id"], item["name"], item.get("qty", 0)))
for row in rows:
print(row)每层一个循环,保留父级 id
用显式栈遍历树
嵌套可能很深时,显式栈能避开递归深度限制,也让待处理的工作看得见。想从左到右访问,就按相反顺序压入子节点;栈是后进先出。
tree = {"name": "menu", "children": [
{"name": "drinks", "children": [{"name": "latte"}, {"name": "tea"}]},
{"name": "food", "children": [{"name": "toast"}]},
]}
stack = [tree]
while stack:
node = stack.pop()
print(node["name"])
stack.extend(reversed(node.get("children", [])))栈保存还没处理的工作
本课要点
- 嵌套数据要一层一层地用方括号读取。
- 字典列表是常见的记录集合。
- 给内层字典的键赋值,就能更新字段。
- 用循环或生成器表达式汇总某个字段。
- 嵌套数据每层都要校验;显式栈让树遍历更可控。
常见错误
- 值还是字典时,只写了一层方括号。
- 不检查记录,就假设每条记录都有同样的键。
- 硬编码索引,而不是遍历记录。
- 子节点压入栈的顺序反了,却奇怪输出为什么倒过来。
创建两个订单字典,放进列表,然后打印总价。
动手试试
改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。
练习本课
12 道题,作答后立即看到解释。