第4章 4.5 综合实战:电商首页 + 商品详情
🎯 开场 3 分钟:为什么要学这个?
上一章我们折腾完了 Vue3 的组合式 API——ref、reactive、自定义 setup 函数,搞得你手都热了吧?
但光有前端武功还不够,你总得有个「后台」来存储商品、管理订单吧?总不能所有数据都写死在前端代码里。
你有没有遇到过这些情况?
- 想做一个「购物车」功能,但不知道数据该存在哪里
- 学了点 Python,但不知道怎么做个「能用」的接口
- 看了 N 个教程,一运行还是只会
print("Hello World")
这一章,我们用 Python + 简单数据结构,从零搭建一个电商后端雏形:支持查询商品列表、筛选分类、查看商品详情。
学完你就能手撸一个「数据驱动」的小项目,不再是纸上谈兵。
🧱 基础 25 分钟:核心概念
4.5.1 Python 字典:电商数据的「档案袋」
是什么?
如果说列表是一排抽屉(用编号 0、1、2 找东西),那字典就是标\n\n
\n\n
\n\n签化文件柜——用名字找东西。
生活中,字典就像你的手机通讯录:不是「第 3 个联系人是张三」,而是「找张三,打 138xxxx」。
为什么要用?
电商场景里,商品有 id、名称、价格、库存、图片URL……一堆属性。用列表的话,你要记「第 0 位是 id,第 1 位是名称,第 2 位是价格」——累死。
用字典,直接 商品["name"] 拿到名字,代码好读一万倍。
怎么用?
# 定义一个商品字典
product = {
"id": 1001,
"name": "iPhone 15 Pro",
"price": 8999,
"stock": 50,
"category": "手机"
}
# 读取数据
print(product["name"]) # 输出: iPhone 15 Pro
print(product["price"]) # 输出: 8999
# 修改数据
product["stock"] = 49 # 卖了一台
print(product["stock"]) # 输出: 49
字典的 key 必须是不可变类型(字符串、数字、元组),value 可以是任意类型。
4.5.2 字典列表:N 个商品的「商品册」
是什么?
一个字典 = 一件商品的信息。那 N 件商品,就是一个字典的列表(List[Dict])。
就像一个衣柜里有多件衣服,每件衣服有自己的属性卡片。
为什么要用?
真实电商有几百上千个商品,总得有个容器把它们装起来、方便遍历查找吧?
怎么用?
# 商品列表(5 个商品)
products = [
{"id": 1, "name": "iPhone 15", "price": 5999, "category": "手机"},
{"id": 2, "name": "MacBook Pro", "price": 9999, "category": "电脑"},
{"id": 3, "name": "AirPods Pro", "price": 1899, "category": "配件"},
{"id": 4, "name": "iPad Air", "price": 4399, "category": "平板"},
{"id": 5, "name": "小米14", "price": 3999, "category": "手机"},
]
# 遍历所有商品
for p in products:
print(f"{p['name']} - ¥{p['price']}")
4.5.3 函数封装:把「操作」变成「工具」
是什么?
函数就是「封装好的做事步骤」。就像微波炉的「解冻」按钮——你不用管它内部怎么工作,按一下就行。
为什么要用?
如果每次查商品都写一大段代码,项目大了你会疯的。函数让你「写一次,用 N 次」。
怎么用?
# 定义一个函数:按分类筛选商品
def filter_by_category(products, category):
"""
参数:
products: 商品列表(字典列表)
category: 要筛选的分类名称
返回:
符合条件的新列表
"""
result = []
for p in products:
if p["category"] == category:
result.append(p)
return result
# 使用函数
phones = filter_by_category(products, "手机")
print(f"手机品类有 {len(phones)} 件商品")
for p in phones:
print(f" - {p['name']}")
小贴士:函数名用
filter_by_category(下划线分隔)还是filterByCategory(驼峰)?Python 社区约定用前者,叫snake_case。
4.5.4 列表推导式:一行代码搞定「筛选+转换」
是什么?
列表推导式是 Python 的独门秘籍——用一行代码完成「遍历+筛选+转换」。
想象点菜流水线:服务员喊「所有热菜」,厨房自动过滤出热菜、装盘、上菜。列表推导式就是这个流水线。
为什么要用?
代码短、运行快、Python 面试必问。
怎么用?
# 传统写法(3 行)
expensive = []
for p in products:
if p["price"] > 5000:
expensive.append(p["name"])
# 列表推导式(1 行搞定)
expensive = [p["name"] for p in products if p["price"] > 5000]
print(expensive) # ['iPhone 15', 'MacBook Pro', 'iPad Air']
语法格式:
[表达式 for item in 可迭代对象 if 条件]
4.5.5 JSON:前后端的「通用语言」
是什么?
JSON 是一种数据格式,Python 字典转成 JSON 后,可以被任何语言(JS、Java、Go…)读取。
就像翻译软件——Python 说「字典」,JSON 翻译成「{key: value}」格式,前端 UniApp 就能用了。
怎么用?
import json
# Python 字典 → JSON 字符串(用于存储/传输)
data = {"name": "iPhone", "price": 5999}
json_str = json.dumps(data, ensure_ascii=False)
print(json_str) # {"name": "iPhone", "price": 5999}
# JSON 字符串 → Python 字典(用于解析)
back_to_dict = json.loads(json_str)
print(back_to_dict["name"]) # iPhone
ensure_ascii=False是为了能正确显示中文,否则会显示 Unicode 转义。
🔥 实战 35 分钟:3 个递进小项目
📦 项目 1(5 分钟):商品列表查询
目标:给定商品列表,查询并展示。
import json
# 模拟数据库:电商商品列表
products = [
{"id": 1, "name": "iPhone 15", "price": 5999, "stock": 100, "category": "手机"},
{"id": 2, "name": "MacBook Pro 14", "price": 9999, "stock": 50, "category": "电脑"},
{"id": 3, "name": "AirPods Pro", "price": 1899, "stock": 200, "category": "配件"},
{"id": 4, "name": "iPad Air", "price": 4399, "stock": 80, "category": "平板"},
{"id": 5, "name": "Apple Watch S9", "price": 3299, "stock": 60, "category": "配件"},
{"id": 6, "name": "小米14 Ultra", "price": 5999, "stock": 30, "category": "手机"},
{"id": 7, "name": "华为Mate60", "price": 6999, "stock": 25, "category": "手机"},
{"id": 8, "name": "ThinkPad X1", "price": 8999, "stock": 40, "category": "电脑"},
]
def get_all_products():
"""返回所有商品列表"""
return products
def display_products(product_list):
"""格式化展示商品"""
print("\n" + "=" * 50)
print(f"{'ID':<6}{'商品名称':<20}{'价格':<10}{'库存':<8}{'分类'}")
print("-" * 50)
for p in product_list:
print(f"{p['id']:<6}{p['name']:<20}¥{p['price']:<8}{p['stock']:<8}{p['category']}")
print("=" * 50)
# 运行
all_products = get_all_products()
display_products(all_products)
预期输出:
==================================================
ID 商品名称 价格 库存 分类
--------------------------------------------------
1 iPhone 15 ¥5999 100 手机
2 MacBook Pro 14 ¥9999 50 电脑
3 AirPods Pro ¥1899 200 配件
4 iPad Air ¥4399 80 平板
5 Apple Watch S9 ¥3299 60 配件
6 小米14 Ultra ¥5999 30 手机
7 华为Mate60 ¥6999 25 手机
8 ThinkPad X1 ¥8999 40 电脑
==================================================
一句话:这段代码用字典列表存储商品数据,用函数封装查询逻辑,方便后续复用。
📦 项目 2(15 分钟):分类筛选 + 价格区间
目标:用户可以按「分类」筛选、按「价格区间」过滤,支持多个筛选条件组合。
import json
products = [
{"id": 1, "name": "iPhone 15", "price": 5999, "stock": 100, "category": "手机", "sales": 5200},
{"id": 2, "name": "MacBook Pro 14", "price": 9999, "stock": 50, "category": "电脑", "sales": 1200},
{"id": 3, "name": "AirPods Pro", "price": 1899, "stock": 200, "category": "配件", "sales": 8900},
{"id": 4, "name": "iPad Air", "price": 4399, "stock": 80, "category": "平板", "sales": 3400},
{"id": 5, "name": "Apple Watch S9", "price": 3299, "stock": 60, "category": "配件", "sales": 4500},
{"id": 6, "name": "小米14 Ultra", "price": 5999, "stock": 30, "category": "手机", "sales": 2800},
{"id": 7, "name": "华为Mate60", "price": 6999, "stock": 25, "category": "手机", "sales": 3100},
{"id": 8, "name": "ThinkPad X1", "price": 8999, "stock": 40, "category": "电脑", "sales": 980},
]
def filter_products(products, category=None, min_price=None, max_price=None):
"""
多条件筛选商品
参数:
category: 分类名称(可选)
min_price: 最低价格(可选)
max_price: 最高价格(可选)
"""
result = products
# 分类筛选
if category:
result = [p for p in result if p["category"] == category]
# 最低价筛选
if min_price is not None:
result = [p for p in result if p["price"] >= min_price]
# 最高价筛选
if max_price is not None:
result = [p for p in result if p["price"] <= max_price]
return result
def sort_products(products, sort_by="sales", reverse=True):
"""
按指定字段排序商品
参数:
sort_by: 排序字段(sales/price/stock)
reverse: True 为降序,False 为升序
"""
return sorted(products, key=lambda x: x[sort_by], reverse=reverse)
# ========== 演示 ==========
print("【场景1】查看所有手机")
phones = filter_products(products, category="手机")
for p in phones:
print(f" {p['name']} ¥{p['price']}")
print("\n【场景2】查看 3000-6000 元的商品")
mid_range = filter_products(products, min_price=3000, max_price=6000)
for p in mid_range:
print(f" {p['name']} ¥{p['price']}")
print("\n【场景3】按销量排序(前3名)")
top_sales = sort_products(products, sort_by="sales", reverse=True)[:3]
for i, p in enumerate(top_sales, 1):
print(f" 第{i}名: {p['name']} 销量={p['sales']}")
# 导出为 JSON(模拟接口返回)
json_output = json.dumps(mid_range, ensure_ascii=False, indent=2)
print("\n【JSON 输出示例】")
print(json_output)
预期输出:
【场景1】查看所有手机
iPhone 15 ¥5999
小米14 Ultra ¥5999
华为Mate60 ¥6999
【场景2】查看 3000-6000 元的商品
iPhone 15 ¥5999
iPad Air ¥4399
Apple Watch S9 ¥3299
小米14 Ultra ¥5999
【场景3】按销量排序(前3名)
第1名: AirPods Pro 销量=8900
第2名: iPhone 15 销量=5200
第3名: Apple Watch S9 销量=4500
【JSON 输出示例】
[
{
"id": 1,
"name": "iPhone 15",
"price": 5999,
...
}
]
一句话:函数参数设为
None(而不是直接不传)是为了区分「没传」和「传了个空」,这样多个筛选条件可以随意组合。
📦 项目 3(15 分钟):购物车 + 订单模拟
目标:做一个简易购物车,支持添加商品、计算总价、生成订单。
import json
from datetime import datetime
products = [
{"id": 1, "name": "iPhone 15", "price": 5999, "stock": 100, "category": "手机"},
{"id": 2, "name": "MacBook Pro 14", "price": 9999, "stock": 50, "category": "电脑"},
{"id": 3, "name": "AirPods Pro", "price": 1899, "stock": 200, "category": "配件"},
]
class ShoppingCart:
"""购物车类"""
def __init__(self):
self.items = [] # 购物车里的商品
def add_item(self, product_id, quantity=1):
"""添加商品到购物车"""
# 查找商品
product = next((p for p in products if p["id"] == product_id), None)
if not product:
print(f"❌ 商品ID {product_id} 不存在")
return False
# 检查库存
if product["stock"] < quantity:
print(f"❌ {product['name']} 库存不足(剩余 {product['stock']})")
return False
# 检查购物车是否已有该商品
existing = next((item for item in self.items if item["product"]["id"] == product_id), None)
if existing:
existing["quantity"] += quantity
else:
self.items.append({
"product": product,
"quantity": quantity
})
print(f"✅ 已添加 {product['name']} x{quantity} 到购物车")
return True
def remove_item(self, product_id):
"""从购物车移除商品"""
self.items = [item for item in self.items if item["product"]["id"] != product_id]
print(f"🗑️ 已从购物车移除商品ID {product_id}")
def get_total(self):
"""计算总金额"""
return sum(item["product"]["price"] * item["quantity"] for item in self.items)
def view_cart(self):
"""查看购物车内容"""
if not self.items:
print("🛒 购物车是空的")
return
print("\n" + "=" * 50)
print("🛒 购物车内容")
print("-" * 50)
for item in self.items:
p = item["product"]
subtotal = p["price"] * item["quantity"]
print(f"{p['name']:<20} x{item['quantity']} = ¥{subtotal}")
print("-" * 50)
print(f"{'总计':<20} ¥{self.get_total()}")
print("=" * 50)
def checkout(self):
"""结算:生成订单"""
if not self.items:
print("❌ 购物车是空的,无法结算")
return None
# 生成订单
order = {
"order_id": f"ORD{datetime.now().strftime('%Y%m%d%H%M%S')}",
"created_at": datetime.now().isoformat(),
"items": self.items.copy(),
"total": self.get_total(),
"status": "已支付"
}
# 更新库存
for item in self.items:
p = item["product"]
p["stock"] -= item["quantity"]
# 清空购物车
self.items = []
print(f"✅ 订单生成成功!订单号:{order['order_id']}")
print(f"💰 实付金额:¥{order['total']}")
return order
# ========== 演示 ==========
cart = ShoppingCart()
print("【第1步】添加商品到购物车")
cart.add_item(1, 1) # iPhone 15
cart.add_item(3, 2) # AirPods Pro x2
cart.add_item(2, 1) # MacBook Pro 14
print("\n【第2步】查看购物车")
cart.view_cart()
print("\n【第3步】再添加一台 iPhone 15(购物车里已有一个,再加一个)")
cart.add_item(1, 1)
print("\n【第4步】再次查看购物车")
cart.view_cart()
print("\n【第5步】结算!")
order = cart.checkout()
if order:
print(f"\n📦 订单详情:")
print(json.dumps(order, ensure_ascii=False, indent=2))
预期输出:
【第1步】添加商品到购物车
✅ 已添加 iPhone 15 x1 到购物车
✅ 已添加 AirPods Pro x2 到购物车
✅ 已添加 MacBook Pro 14 x1 到购物车
【第2步】查看购物车
==================================================
🛒 购物车内容
--------------------------------------------------
iPhone 15 x1 = ¥5999
AirPods Pro x2 = ¥3798
MacBook Pro 14 x1 = ¥9999
--------------------------------------------------
总计 ¥19796
==================================================
【第3步】再添加一台 iPhone 15(购物车里已有一个,再加一个)
✅ 已添加 iPhone 15 x1 到购物车
【第4步】再次查看购物车
==================================================
🛒 购物车内容
--------------------------------------------------
iPhone 15 x1 = ¥5999
AirPods Pro x2 = ¥3798
MacBook Pro 14 x1 = ¥9999
iPhone 15 x1 = ¥5999
--------------------------------------------------
总计 ¥19796 ← 等等,这里有问题!数量没累加
==================================================
【第5步】结算!
✅ 订单生成成功!订单号:ORD20250626143025
💰 实付金额:¥19796
📦 订单详情:
{
"order_id": "ORD20250626143025",
"created_at": "2026-06-26T14:30:25.xxx",
"items": [...],
"total": 19796,
"status": "已支付"
}
⚠️ 这里暴露了一个问题:同个商品被重复添加成了两条记录。进阶练习里会让你修复这个 bug。
💪 进阶 20 分钟:常见坑 + 性能小贴士
❌ 坑 1:可变默认参数
# ❌ 错误写法
def add_item(items=[]): # 默认参数是列表,这是可变对象!
items.append("新商品")
return items
# 调用两次
print(add_item()) # ['新商品']
print(add_item()) # ['新商品', '新商品'] ← 累积了!
# ✅ 正确写法
def add_item(items=None):
if items is None:
items = []
items.append("新商品")
return items
说白了:默认参数只在函数定义时创建一次。如果它是可变对象,后续调用会共享同一个对象。
❌ 坑 2:字典 key 不存在
product = {"name": "iPhone", "price": 5999}
# ❌ 错误:key 不存在会报错
# print(product["stock"]) # KeyError: 'stock'
# ✅ 正确:用 get() 方法,不存在返回默认值
print(product.get("stock", 0)) # 0
print(product.get("name")) # iPhone(存在,正常返回)
❌ 坑 3:循环修改列表
nums = [1, 2, 3, 4, 5]
# ❌ 错误:边遍历边删除,可能漏元素
for n in nums:
if n % 2 == 0:
nums.remove(n) # 危险!
# ✅ 正确:创建新列表
nums = [n for n in nums if n % 2 != 0]
print(nums) # [1, 3, 5]
❌ 坑 4:== 和 is 混淆
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # True ← 值相等
print(a is b) # False ← 不是同一个对象
c = a
print(a is c) # True ← 同一个对象
记忆口诀:
==问「值相等吗」,is问「是同一个人吗」。
❌ 坑 5:列表推导式副作用
# ❌ 错误:列表推导式里有副作用
results = [y := x * 2, x for x in range(5)] # 尽量别用 walrus operator
# ✅ 正确:保持简洁,分步写
doubled = [x * 2 for x in range(5)]
⚡ 性能小贴士:大量数据用生成器
import sys
# 列表:一次性和全部装进内存
big_list = [x ** 2 for x in range(100000)]
print(f"列表占用:{sys.getsizeof(big_list)} bytes")
# 生成器:按需产生,用多少占多少
big_gen = (x ** 2 for x in range(100000))
print(f"生成器占用:{sys.getsizeof(big_gen)} bytes")
生成器就像「自来水厂」——你打开水龙头才来水,不用提前建一个大水库。
🔍 调试技巧:print 大法
def buggy_function(data):
print(f"📥 入参:{data}") # 入口打印
result = data * 2
print(f"📤 结果:{result}") # 出口打印
return result
buggy_function(5)
# 📥 入参:5
# 📤 结果:10
简单场景用 print,复杂项目用
logging模块(可以控制输出级别)。
✏️ 练习题 + 作业题
练习 1(1 分钟):抄改变量
# 原始代码:筛选手机
phones = [p for p in products if p["category"] == "手机"]
# 练习:筛选"电脑"分类
# 预期输出:MacBook Pro 14, ThinkPad X1
练习 2(2 分钟):加个判断
products = [{"name": "iPhone", "price": 5999}, {"name": "AirPods", "price": 1899}]
# 原始:打印所有商品
for p in products:
print(p["name"])
# 练习:只打印价格 > 3000 的商品
# 预期输出:iPhone
练习 3(2 分钟):新数据处理
# 练习:用列表推导式,从下面这个销售数据中找出「季度销售额 > 100万」的月份
sales_data = [
{"month": "1月", "sales": 80},
{"month": "2月", "sales": 120},
{"month": "3月", "sales": 95},
{"month": "4月", "sales": 150},
]
# 提示:sales_data 是一个字典列表,sales 是销售额字段
# 预期输出:[{"month": "2月", "sales": 120}, {"month": "4月", "sales": 150}]
练习 4(3 分钟):组合两个函数
# 项目 2 有 filter_products 和 sort_products
# 练习:先筛选「配件」分类,再按价格升序排列
categories = [
{"name": "AirPods", "price": 1899, "category": "配件"},
{"name": "Watch", "price": 3299, "category": "配件"},
{"name": "手机壳", "price": 99, "category": "配件"},
]
# 提示:先 filter 再 sort(链式调用)
# 预期输出:手机壳(99) → AirPods(1899) → Watch(3299)
练习 5(2 分钟):Debug 分析
# 用户运行这段代码报错,请分析原因
cart = ShoppingCart()
cart.add_item(1, 50) # 报错:库存不足
print(cart.items) # 想看购物车内容
# 报错信息:❌ iPhone 15 库存不足(剩余 100)
# 问题:用户买了 50 台,为什么报库存不足?
# 提示:检查库存判断逻辑是否有问题
📝 作业:做一个「商品收藏夹」小工具
需求描述:
做一个命令行工具,模拟用户收藏商品、查看收藏夹、计算收藏商品总价值。
功能点:
1. 添加商品到收藏夹(根据商品ID)
2. 查看收藏夹所有商品
3. 计算收藏夹商品总价
4. 移除收藏夹中的商品
5. 支持从 JSON 文件保存/加载收藏夹
加分项:
1. 支持按价格排序显示收藏夹
2. 添加「猜你喜欢」功能:根据已收藏商品的分类,推荐同分类其他商品
验收标准:
- 能运行不报错
- 输出格式清晰
- 代码有适当注释
- 用到了本章至少 3 个核心知识点(字典、列表推导式、函数、JSON)
提交方式:评论区贴代码,或打包成 .py 文件下载链接
📚 总结 + 资源
本文学了 3 个核心点:
- ✅ 字典和字典列表:电商数据的「档案袋」和「商品册」
- ✅ 函数封装 + 列表推导式:让代码复用、简洁、高效
- ✅ JSON 序列化:Python 和前端沟通的「通用语言」
延伸资源:
| 资源 | 链接 | 适合谁 |
|---|---|---|
| Python 官方文档 · 字典 | docs.python.org/3/tutorial/datastructures.html#dictionaries | 查漏补缺 |
| 《Python 编程:从入门到实践》 | 人民邮电出版社 | 系统学习 |
| 知乎 · Python 入门教程(最通俗) | zhihu.com | 入门扫盲 |
互动钩子:
🎯 你在写爬虫或数据处理时,是怎么组织商品数据的?用过哪些奇怪的数据结构?
评论区聊聊,老粉优先回复!
下一章我们要进入「微信小程序原生能力」——学了这么久 Python,是时候让你的 UniApp 项目真正跑在小程序上了。敬请期待!

评论(0)