第6章 6.5 综合实战:跨端电商 App

⏱️ 学习时长:90 分钟 | 🎯 难度:进阶 | 📖 第 30/45 章

🎯 开场 3 分钟:为什么要学这个?

上一章我们折腾了 nvue 原生渲染,搞定了「条件编译」这个香饽饽——一套代码,多端生效,爽不爽?

但光会页面布局还不够,真正的电商 App 离不开数据流转。你有没有想过:

  • 商品列表从哪来?订单怎么生成?
  • 用户下单后,库存怎么扣减?
  • 那些「限时秒杀」「拼团活动」背后是什么逻辑?

这一章,我们用 Python 写一个电商数据处理工具,模拟电商 App 的核心业务流程。说是 Python,其实是给下一章的 TypeScript 改造打前站——你先在 Python 里把业务逻辑搞明白,换成 TypeScript 就是换件衣服的事。

学完这章,你就能:
- ✅ 用 Python 处理商品、订单、用户数据
- ✅ 理解电商核心模块的数据流
- ✅ 为下一章 TypeScript 改造做好准备


🧱 基础 25 分钟:核心概念

什么\n\nSimple tech illustration expla\n\nAI comic creation scene, creat\n\n是电商数据模型?

💡 生活类比:电商数据模型就像餐厅的菜单 + 订单本
- 商品 = 菜单上的菜
- 购物车 = 你点菜的清单
- 订单 = 服务员记下的正式订单

电商 App 本质是数据流转

用户浏览商品 → 加入购物车 → 下单 → 支付 → 商家发货 → 收货确认

每一步都在操作数据。我们用 Python 定义几个核心数据类:

# 定义商品模型
class Product:
def __init__(self, product_id, name, price, stock):
    self.product_id = product_id    # 商品ID
    self.name = name                  # 商品名称
    self.price = price                # 价格(元)
    self.stock = stock                # 库存(件)

# 定义购物车项
class CartItem:
def __init__(self, product, quantity):
    self.product = product            # 商品对象
    self.quantity = quantity          # 购买数量

# 定义订单模型
class Order:
def __init__(self, order_id, items):
    self.order_id = order_id          # 订单号
    self.items = items                # 购物车项列表
    self.status = "pending"            # 订单状态:pending/paid/shipped/completed

为什么要用类来组织数据?

💡 痛点:不用类的话,数据散落各处,改一处要改十处
用了类之后,数据 + 行为打包在一起,逻辑清晰

实战:创建商品和购物车

# 初始化几个商品
products = [
Product("P001", "iPhone 15", 5999, 100),
Product("P002", "AirPods Pro", 1999, 200),
Product("P003", "MacBook Air", 8999, 50),
]

# 创建购物车
cart = []

# 添加商品到购物车(模拟用户点击"加入购物车")
def add_to_cart(product_id, quantity):
for p in products:
    if p.product_id == product_id:
        cart.append(CartItem(p, quantity))
        print(f"✅ 已添加 {p.name} x{quantity} 到购物车")
        return
print("❌ 商品不存在")

# 测试加入购物车
add_to_cart("P001", 1)
add_to_cart("P002", 2)

预期输出:

✅ 已添加 iPhone 15 x1 到购物车
✅ 已添加 AirPods Pro x2 到购物车

什么是订单总价计算?

💡 生活类比:结账 = 把你点的东西加起来,乘以单价,再算折扣

订单总价怎么算?遍历购物车,每项 商品价格 × 数量,加起来:

# 计算购物车总价
def calculate_total(cart_items):
total = 0
for item in cart_items:
    total += item.product.price * item.quantity
return total

# 试算一下
total = calculate_total(cart)
print(f"购物车总计:{total} 元")

预期输出:

购物车总计:9997 元

什么是库存扣减?

💡 痛点:超卖!两个人同时买最后一件,都显示成功,结果发不出货
解决:下单前检查库存,扣减时加锁(或用事务)

# 下单并扣减库存
def create_order(cart_items):
# 1. 先检查库存够不够
for item in cart_items:
    if item.product.stock < item.quantity:
        print(f"❌ 库存不足:{item.product.name} 库存{item.product.stock},需要{item.quantity}")
        return None

# 2. 库存够,生成订单
order_id = "ORD" + "20240115" + "001"
order = Order(order_id, cart_items)

# 3. 扣减库存
for item in cart_items:
    item.product.stock -= item.quantity

# 4. 清空购物车
cart_items.clear()

order.status = "paid"
print(f"✅ 订单创建成功!订单号:{order_id}")
return order

# 执行下单
order = create_order(cart)
if order:
print(f"订单状态:{order.status}")

预期输出:

✅ 订单创建成功!订单号:ORD20240115001
订单状态:paid

🔥 实战 35 分钟:3 个递进小项目

项目 1(5 分钟):购物车小工具

跟着抄就能跑,体验完整的「加购物车 → 查看 → 清空」流程:

# 项目1:购物车管理工具
class ShoppingCart:
def __init__(self):
    self.items = []

def add(self, product, quantity):
    self.items.append(CartItem(product, quantity))
    print(f"🛒 {product.name} x{quantity} 已加入")

def view(self):
    if not self.items:
        print("购物车是空的")
        return
    print("\n===== 购物车 =====")
    for item in self.items:
        print(f"{item.product.name} x{item.quantity} = {item.product.price * item.quantity}元")
    print(f"总计:{calculate_total(self.items)}元")

def clear(self):
    self.items.clear()
    print("🗑️ 购物车已清空")

# 使用
cart = ShoppingCart()
cart.add(Product("P001", "iPhone 15", 5999, 100), 1)
cart.add(Product("P002", "AirPods Pro", 1999, 200), 1)
cart.view()

预期输出:

🛒 iPhone 15 x1 已加入
🛒 AirPods Pro x1 已加入

===== 购物车 =====
iPhone 15 x1 = 5999元
AirPods Pro x1 = 1999元
总计:7998元

项目 2(15 分钟):从 JSON 文件读取商品数据

真实项目不会写死数据,一般从文件或 API 读取。新建 products.json

[
{"product_id": "P001", "name": "iPhone 15", "price": 5999, "stock": 100},
{"product_id": "P002", "name": "AirPods Pro", "price": 1999, "stock": 200},
{"product_id": "P003", "name": "MacBook Air", "price": 8999, "stock": 50},
{"product_id": "P004", "name": "iPad Air", "price": 4799, "stock": 150},
{"product_id": "P005", "name": "Apple Watch", "price": 2999, "stock": 300}
]

然后用 Python 读取:

import json

# 从JSON文件加载商品数据
def load_products_from_json(filename):
with open(filename, 'r', encoding='utf-8') as f:
    data = json.load(f)
return [Product(p['product_id'], p['name'], p['price'], p['stock']) for p in data]

# 使用
products = load_products_from_json('products.json')

# 显示所有商品
print("===== 商品列表 =====")
for p in products:
print(f"{p.product_id}: {p.name} - {p.price}元 (库存:{p.stock})")

# 查找商品
def find_product(products, product_id):
for p in products:
    if p.product_id == product_id:
        return p
return None

# 搜索
result = find_product(products, "P003")
if result:
print(f"\n🔍 找到:{result.name},价格{result.price}元")

预期输出:

===== 商品列表 =====
P001: iPhone 15 - 5999元 (库存:100)
P002: AirPods Pro - 1999元 (库存:200)
P003: MacBook Air - 8999元 (库存:50)
P004: iPad Air - 4799元 (库存:150)
P005: Apple Watch - 2999元 (库存:300)

🔍 找到:MacBook Air,价格8999元

项目 3(15 分钟):限时秒杀模拟器

组合前两个项目,做一个有点真实用的小工具——限时秒杀系统

import json
import time

class FlashSale:
def __init__(self, products):
    self.products = {p.product_id: p for p in products}
    self.orders = []

def is_stock_available(self, product_id, quantity):
    p = self.products.get(product_id)
    if not p:
        return False, "商品不存在"
    if p.stock < quantity:
        return False, f"库存不足,仅剩{p.stock}件"
    return True, "可以购买"

def flash_buy(self, product_id, quantity, user_id):
    # 检查库存
    available, msg = self.is_stock_available(product_id, quantity)
    if not available:
        return {"success": False, "message": msg}

    # 扣减库存
    self.products[product_id].stock -= quantity

    # 生成订单
    order = {
        "order_id": f"FS{int(time.time())}",
        "user_id": user_id,
        "product_id": product_id,
        "quantity": quantity,
        "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
    }
    self.orders.append(order)

    return {
        "success": True,
        "message": "秒杀成功!",
        "order": order
    }

# 模拟秒杀
flash = FlashSale(products)

# 模拟10个人同时抢P003(库存只有50)
print("===== 限时秒杀开始 =====")
results = []
for i in range(1, 11):
result = flash.flash_buy("P003", 1, f"USER{i}")
results.append(result)
if result["success"]:
    print(f"USER{i} ✅ {result['message']} 订单号:{result['order']['order_id']}")
else:
    print(f"USER{i} ❌ {result['message']}")

# 秒杀结束,检查库存
print(f"\n===== 秒杀结束 =====")
print(f"P003 剩余库存:{flash.products['P003'].stock}")
print(f"成功订单数:{len([o for o in flash.orders if o['product_id'] == 'P003'])}")

预期输出:

===== 限时秒杀开始 =====
USER1 ✅ 秒杀成功! 订单号:FS1705312800
USER2 ✅ 秒杀成功! 订单号:FS1705312801
...(继续)
USER10 ✅ 秒杀成功! 订单号:FS1705312809

===== 秒杀结束 =====
P003 剩余库存:40
成功订单数:10

💪 进阶 20 分钟:常见坑 + 性能小贴士

坑 1:可变默认参数

# ❌ 错误示例:默认参数用了列表,后面会出事
def add_items(product_id, cart=[]):
cart.append(product_id)
return cart

# ✅ 正确写法:默认参数用 None
def add_items_fixed(product_id, cart=None):
if cart is None:
    cart = []
cart.append(product_id)
return cart

坑 2:循环修改列表

# ❌ 错误示例:边遍历边删除,会漏掉元素
cart = [1, 2, 3, 4, 5]
for item in cart:
if item < 3:
    cart.remove(item)

# ✅ 正确写法:用切片或过滤
cart = [item for item in cart if item >= 3]

坑 3:浮点数价格计算

# ❌ 错误示例:浮点数精度问题
total = 0.1 + 0.2
print(total)  # 0.30000000000000004

# ✅ 正确做法:用整数(分)或 Decimal
price_in_cent = 10 + 20  # 用分
print(price_in_cent / 100)  # 0.30

坑 4:字典键不存在

# ❌ 错误示例:键不存在会抛异常
data = {"name": "iPhone"}
print(data["price"])  # KeyError

# ✅ 正确做法:用 get 或默认值
print(data.get("price", 0))  # 0

性能小贴士:批量操作减少循环

# ❌ 低效:循环里查字典
for item in cart:
product = None
for p in products:
    if p.product_id == item.product_id:
        product = p
        break

# ✅ 高效:预先建字典
product_dict = {p.product_id: p for p in products}
for item in cart:
product = product_dict.get(item.product_id)  # O(1) 查找

调试技巧:用 pdb 打打断点

import pdb

def calculate_total(cart_items):
pdb.set_trace()  # 程序会在这里暂停,进入交互式调试
total = 0
for item in cart_items:
    total += item.product.price * item.quantity
return total

运行时看到 (Pdb) 提示,输入 n 单步执行,p 变量名 查看变量值,c 继续运行。


✏️ 练习题 + 作业题

练习题(5 道,10 分钟内完成)

练习 1(2 分钟):改价格
- 输入:把 products.json 里 iPhone 15 改成 5499 元
- 预期输出:重新加载后显示新价格
- 提示:json.load() 后修改,再重新保存

练习 2(2 分钟):加个判断
- 输入:在 calculate_total 里加个判断,如果购物车为空返回 0
- 预期输出:空购物车调用返回 0,不报错
- 提示:if not cart_items: return 0

练习 3(3 分钟):处理新数据
- 输入:用项目 2 的方式加载这个 JSON:{"product_id": "P006", "name": "Vision Pro", "price": 29999, "stock": 20}
- 预期输出:打印出商品信息
- 提示:单个对象不用 json.load() 的列表推导式

练习 4(5 分钟):串接项目
- 输入:把项目 2 的商品加载 + 项目 3 的秒杀逻辑串起来
- 预期输出:能用 JSON 里的商品做秒杀
- 提示:把项目 2 的 products 传进 FlashSale

练习 5(3 分钟):找出 bug
- 输入:下面代码运行会报错,找出原因

data = [{"id": 1}, {"id": 2}]
result = data[2]["id"]  # 哪行错了?
  • 预期输出:说明错误原因
  • 提示:索引从 0 开始

作业题(30 分钟 - 2 小时)

作业:做一个「电商数据统计工具」

  • 需求描述:读取商品和订单数据,输出统计报表
  • 功能点
    1. 从 JSON 读取至少 5 个商品
    2. 生成至少 3 笔订单(模拟下单)
    3. 输出统计:总销售额、总订单数、库存剩余
    4. 找出「爆款」:销量最高的商品
  • 加分项
    1. 按销售额排序商品
    2. 输出 CSV 格式报表
  • 验收标准:代码能跑、输出清晰、有中文注释
  • 提交方式:评论区贴代码或 GitHub 链接

📚 总结 + 资源

本文学了 3 件事:
1. ✅ 用 class 定义商品、购物车、订单模型
2. ✅ 从 JSON 读取数据,用 Python 处理业务逻辑
3. ✅ 理解了电商核心流程:加购 → 下单 → 扣库存

延伸资源:
- 📖 Python 官方文档 - 类
- 📖 《Python编程:从入门到实践》- 第9章类部分
- 🎬 B站:Python 面向对象编程入门


互动钩子: 你有没有被电商「超卖」坑过?或者抢过秒杀没抢到?评论区聊聊,吐槽最多的老粉我优先回复!

📌 下章预告:Python 里业务逻辑搞明白了,但 JavaScript/TypeScript 写起来啥感觉?下一章我们把电商工具用 TypeScript 重写一遍,顺便加上类型检查——「编译时纠错,比运行时报错爽多了」!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。