【测试开发 Python 基础】P02 - 流程控制与函数
本文是《企业级自动化测试实战》系列的第 2 篇。上一篇我们搭建了 Python 环境并生成了 MallLite 项目的商品数据。本篇将学习条件判断、循环和函数,然后用它们为 MallLite 编写商品查询、搜索、分页等核心逻辑。
前言
上一篇我们用变量和数据类型生成了商品数据文件。但数据生成出来只是放在那里,真正的项目需要对数据进行操作:查找某个商品、按分类筛选、分页展示、计算总价……
这些操作都需要用到两个核心能力:流程控制(告诉程序在什么情况下做什么)和函数(把一段可复用的逻辑包起来)。
今天的任务:
- 掌握 if / elif / else 条件判断
- 掌握 for / while 循环
- 学会定义和调用函数
- 学会函数的参数和返回值
- 为 MallLite 编写商品查询、搜索、分页函数
- 学会列表推导式(Python 最优雅的特性之一)
一、条件判断 if / elif / else
1.1 基本语法
程序需要根据不同情况执行不同的代码。比如:库存大于 0 显示"有货",否则显示"缺货"。
stock = 50
if stock > 0:
print("有货")
else:
print("缺货")
# 输出:有货
注意两点:
- 条件后面要加冒号
: - 代码块要缩进 4 个空格(Python 用缩进表示代码层级,不用大括号)
1.2 多条件判断 elif
如果需要判断多个条件,用 elif(else if 的缩写):
price = 8999
if price < 500:
print("低价商品")
elif price < 2000:
print("中价商品")
elif price < 5000:
print("高价商品")
else:
print("奢侈品")
# 输出:奢侈品
判断顺序从上到下,一旦某个条件成立,执行对应的代码块,后面的 elif 和 else 全部跳过。
1.3 条件表达式
常用的比较运算符:
| 运算符 | 含义 | 示例 |
|---|---|---|
== | 等于 | price == 999 |
!= | 不等于 | status != "sold_out" |
> | 大于 | stock > 0 |
< | 小于 | price < 1000 |
>= | 大于等于 | rating >= 4.5 |
<= | 小于等于 | quantity <= 0 |
in | 包含 | "iPhone" in name |
not in | 不包含 | "测试" not in name |
1.4 逻辑运算符
多个条件组合:
# and:两个条件都满足
if price > 1000 and stock > 0:
print("高价且有货的商品")
# or:满足其中一个
if category == "手机" or category == "平板":
print("移动设备")
# not:取反
if not is_new:
print("非新品")
1.5 用在 MallLite 的场景
# 根据价格区间给商品打标签
price = 8999
if price < 500:
tag = "平价"
elif price < 3000:
tag = "中端"
elif price < 8000:
tag = "高端"
else:
tag = "旗舰"
print(f"¥{price} 属于:{tag}商品")
# 输出:¥8999 属于:旗舰商品
二、循环 for / while
2.1 for 循环
for 循环用来遍历一个序列(列表、字符串、range 等):
# 遍历列表
fruits = ["苹果", "香蕉", "橘子"]
for fruit in fruits:
print(f"我喜欢吃{fruit}")
# 输出:
# 我喜欢吃苹果
# 我喜欢吃香蕉
# 我喜欢吃橘子
2.2 range() 函数
range() 生成一个数字序列,常用于循环指定次数:
# range(5) 生成 0, 1, 2, 3, 4
for i in range(5):
print(i)
# range(1, 6) 生成 1, 2, 3, 4, 5
for i in range(1, 6):
print(f"第 {i} 页")
# range(0, 20, 5) 生成 0, 5, 10, 15(步长为 5)
for i in range(0, 20, 5):
print(i)
2.3 带索引的遍历
有时候不仅需要元素,还需要它的位置(索引)。用 enumerate():
products = ["iPhone", "MacBook", "iPad"]
for index, name in enumerate(products):
print(f" {index + 1}. {name}")
# 输出:
# 1. iPhone
# 2. MacBook
# 3. iPad
2.4 while 循环
while 循环在条件为真时一直执行:
# 翻页示例:从第 1 页翻到最后一页
page = 1
total_pages = 5
while page <= total_pages:
print(f"正在加载第 {page} 页...")
page = page + 1
print("所有页面加载完成")
# 输出:
# 正在加载第 1 页...
# 正在加载第 2 页...
# 正在加载第 3 页...
# 正在加载第 4 页...
# 正在加载第 5 页...
# 所有页面加载完成
2.5 break 和 continue
break:立即跳出整个循环。
# 找到第一个价格低于 1000 的商品就停止
prices = [8999, 5999, 6999, 4999, 399, 1899]
for price in prices:
if price < 1000:
print(f"找到低价商品:¥{price}")
break
print(f"¥{price} 太贵了,跳过")
# 输出:
# ¥8999 太贵了,跳过
# ¥5999 太贵了,跳过
# ¥6999 太贵了,跳过
# ¥4999 太贵了,跳过
# 找到低价商品:¥399
continue:跳过本次循环,继续下一次。
# 打印所有有库存的商品,跳过缺货的
products = [
{"name": "iPhone", "stock": 100},
{"name": "MacBook", "stock": 0},
{"name": "iPad", "stock": 50},
{"name": "AirPods", "stock": 0},
]
for p in products:
if p["stock"] == 0:
continue # 跳过缺货商品
print(f"有货:{p['name']}(库存 {p['stock']})")
# 输出:
# 有货:iPhone(库存 100)
# 有货:iPad(库存 50)
2.6 循环中的 else
Python 独有的语法:for/while 循环正常结束(没有被 break 中断)时,执行 else 块。
# 搜索商品,如果遍历完都没找到,提示未找到
products = ["iPhone", "MacBook", "iPad"]
keyword = "华为"
for name in products:
if keyword in name:
print(f"找到:{name}")
break
else:
print(f"未找到包含'{keyword}'的商品")
# 输出:未找到包含'华为'的商品
三、列表推导式(Python 最优雅的写法)
列表推导式是 Python 的招牌特性,一行代码就能完成"遍历 + 筛选 + 转换"。在后面的自动化测试代码中会大量使用。
3.1 基本语法
# 普通写法:获取所有商品名
names = []
for p in products:
names.append(p["name"])
# 列表推导式:一行搞定
names = [p["name"] for p in products]
3.2 带条件筛选
# 筛选价格低于 5000 的商品名
cheap = [p["name"] for p in products if p["price"] < 5000]
# 筛选所有手机类商品
phones = [p for p in products if p["category"] == "手机"]
# 筛选新品
new_products = [p["name"] for p in products if p["is_new"]]
3.3 转换数据
# 获取所有价格并转成字符串
price_strings = [f"¥{p['price']}" for p in products]
# 生成商品摘要
summaries = [f"{p['name']}(¥{p['price']})" for p in products]
3.4 对比普通写法和列表推导式
| 需求 | 普通写法 | 列表推导式 |
|---|---|---|
| 获取所有商品名 | names = []for p in products: names.append(p["name"]) | [p["name"] for p in products] |
| 筛选手机 | phones = []for p in products: if p["category"] == "手机": phones.append(p) | [p for p in products if p["category"] == "手机"] |
| 获取所有价格 | prices = []for p in products: prices.append(p["price"]) | [p["price"] for p in products] |
列表推导式可读性更高,代码更短,是 Pythonic 的写法。
四、函数
4.1 为什么要用函数
假设你在 10 个地方都需要"根据 ID 查找商品"这个逻辑。不用函数的话,同样的代码要写 10 遍。有了函数,写一次,到处调用。
# 没有函数:重复代码
# 在搜索功能中
for p in products:
if p["id"] == 3:
print(p["name"])
# 在购物车功能中
for p in products:
if p["id"] == 3:
print(p["price"])
# 在订单功能中
for p in products:
if p["id"] == 3:
print(p["stock"])
# 有函数:写一次,用三次
def get_product_by_id(product_id):
for p in products:
if p["id"] == product_id:
return p
return None
product = get_product_by_id(3)
print(product["name"])
print(product["price"])
print(product["stock"])
4.2 定义函数的基本语法
def 函数名(参数1, 参数2):
"""函数说明(可选)"""
# 函数体
return 返回值
一个最简单的例子:
def greet(name):
"""打招呼函数"""
return f"你好,{name}!"
# 调用函数
message = greet("张三")
print(message) # 输出:你好,张三!
4.3 参数类型
# 位置参数(最常用)
def add(a, b):
return a + b
result = add(3, 5) # a=3, b=5
# 默认参数(有默认值,调用时可以省略)
def greet(name, greeting="你好"):
return f"{greeting},{name}!"
greet("张三") # "你好,张三!"
greet("张三", "早上好") # "早上好,张三!"
# 关键字参数(指定参数名,顺序随意)
def create_user(username, age, role="user"):
return {"username": username, "age": age, "role": role}
create_user(age=25, username="张三") # 顺序随意
create_user("张三", 25, role="admin") # 指定 role
4.4 返回值
# 返回单个值
def get_price(product):
return product["price"]
# 返回多个值(实际上返回一个元组)
def get_price_range(products):
prices = [p["price"] for p in products]
return min(prices), max(prices)
lowest, highest = get_price_range(products)
print(f"价格区间:¥{lowest} - ¥{highest}")
# 返回字典
def get_product_summary(product):
return {
"name": product["name"],
"price": product["price"],
"in_stock": product["stock"] > 0
}
# 没有 return 或 return 后没有值,返回 None
def print_product(product):
print(product["name"])
# 隐式返回 None
4.5 函数文档字符串
函数体的第一行用三引号写的字符串,就是这个函数的说明文档。好的文档字符串能让别人(包括未来的你)快速理解函数的用途:
def search_products(products, keyword):
"""
根据关键词搜索商品(模糊匹配名称)
参数:
products: 商品列表
keyword: 搜索关键词
返回:
包含关键词的商品列表
"""
return [p for p in products if keyword.lower() in p["name"].lower()]
在 IDE 中调用函数时,鼠标悬停就能看到这段说明。
五、动手实战:为 MallLite 编写核心函数
学完以上知识,现在来为 MallLite 项目编写一组核心函数。
创建新文件 mall_functions.py:
"""
MallLite 电商系统 - 核心业务函数
功能:商品查询、搜索、筛选、分页、购物车、用户验证
"""
import json
import os
# ========================================
# 第一步:加载数据
# ========================================
data_dir = "data"
def load_json(filename):
"""加载 JSON 数据文件"""
filepath = os.path.join(data_dir, filename)
with open(filepath, "r", encoding="utf-8") as f:
return json.load(f)
products = load_json("products.json")
users = load_json("users.json")
categories = load_json("categories.json")
print(f"加载完成:{len(products)} 个商品,{len(users)} 个用户,{len(categories)} 个分类")
print("=" * 60)
# ========================================
# 第二步:商品查询函数
# ========================================
def get_product_by_id(product_id):
"""
根据商品 ID 查询商品
参数:
product_id: 商品 ID
返回:
找到则返回商品字典,找不到返回 None
"""
for p in products:
if p["id"] == product_id:
return p
return None
def get_products_by_category(category):
"""
根据分类名称获取商品列表
参数:
category: 分类名称(如 "手机")
返回:
该分类下的所有商品列表
"""
result = []
for p in products:
if p["category"] == category:
result.append(p)
return result
def get_new_products():
"""获取所有新品"""
result = []
for p in products:
if p["is_new"]:
result.append(p)
return result
def get_products_by_price_range(min_price, max_price):
"""
按价格区间筛选商品
参数:
min_price: 最低价格
max_price: 最高价格
返回:
价格在区间内的商品列表
"""
result = []
for p in products:
if min_price <= p["price"] <= max_price:
result.append(p)
return result
# 测试查询函数
print("【商品查询】")
print("-" * 60)
product = get_product_by_id(1)
print(f"ID=1 的商品:{product['name']}(¥{product['price']})")
product = get_product_by_id(999)
print(f"ID=999 的商品:{product}") # None
phones = get_products_by_category("手机")
print(f"\n手机分类共 {len(phones)} 个商品:")
for p in phones:
print(f" - {p['name']}(¥{p['price']})")
new_items = get_new_products()
print(f"\n新品共 {len(new_items)} 个:")
for p in new_items:
print(f" - {p['name']}(¥{p['price']})")
cheap = get_products_by_price_range(0, 2000)
print(f"\n¥2000 以下的商品共 {len(cheap)} 个:")
for p in cheap:
print(f" - {p['name']}(¥{p['price']})")
print()
# ========================================
# 第三步:商品搜索函数
# ========================================
def search_products(keyword):
"""
搜索商品(模糊匹配名称和描述)
参数:
keyword: 搜索关键词
返回:
名称或描述中包含关键词的商品列表
"""
keyword_lower = keyword.lower()
results = []
for p in products:
name_match = keyword_lower in p["name"].lower()
desc_match = keyword_lower in p["description"].lower()
if name_match or desc_match:
results.append(p)
return results
def highlight_keyword(text, keyword):
"""
在文本中高亮关键词(用 【】 包裹)
参数:
text: 原始文本
keyword: 要高亮的关键词
返回:
高亮后的文本
"""
result = text
keyword_lower = keyword.lower()
text_lower = text.lower()
start = text_lower.find(keyword_lower)
if start != -1:
end = start + len(keyword)
result = text[:start] + "【" + text[start:end] + "】" + text[end:]
return result
# 测试搜索函数
print("【商品搜索】")
print("-" * 60)
search_keyword = "Pro"
results = search_products(search_keyword)
print(f"搜索 '{search_keyword}',找到 {len(results)} 个结果:")
for p in results:
highlighted_name = highlight_keyword(p["name"], search_keyword)
print(f" - {highlighted_name}(¥{p['price']})")
print()
search_keyword = "芯片"
results = search_products(search_keyword)
print(f"搜索 '{search_keyword}',找到 {len(results)} 个结果:")
for p in results:
print(f" - {p['name']}:{highlight_keyword(p['description'], search_keyword)}")
print()
search_keyword = "不存在的商品xyz"
results = search_products(search_keyword)
print(f"搜索 '{search_keyword}',找到 {len(results)} 个结果")
print()
# ========================================
# 第四步:分页函数
# ========================================
def paginate(data, page=1, page_size=5):
"""
对数据进行分页
参数:
data: 要分页的数据列表
page: 页码(从 1 开始)
page_size: 每页数量(默认 5)
返回:
分页结果字典,包含总数、页码、每页数量、数据、总页数
"""
total = len(data)
total_pages = (total + page_size - 1) // page_size # 向上取整
# 页码边界处理
if page < 1:
page = 1
if page > total_pages and total_pages > 0:
page = total_pages
start = (page - 1) * page_size
end = start + page_size
return {
"total": total,
"page": page,
"page_size": page_size,
"total_pages": total_pages,
"items": data[start:end]
}
def print_pagination(result):
"""美观地打印分页结果"""
print(f" 总计:{result['total']} 条")
print(f" 页码:第 {result['page']}/{result['total_pages']} 页")
print(f" 本页:{len(result['items'])} 条")
for item in result["items"]:
print(f" - {item['name']}(¥{item['price']})")
# 测试分页函数
print("【分页功能】")
print("-" * 60)
print("\n全部商品,第 1 页(每页 5 条):")
page1 = paginate(products, page=1, page_size=5)
print_pagination(page1)
print("\n全部商品,第 2 页:")
page2 = paginate(products, page=2, page_size=5)
print_pagination(page2)
print("\n全部商品,第 3 页:")
page3 = paginate(products, page=3, page_size=5)
print_pagination(page3)
# 分类 + 分页组合
print("\n手机分类,第 1 页(每页 2 条):")
phones = get_products_by_category("手机")
phones_page = paginate(phones, page=1, page_size=2)
print_pagination(phones_page)
# 边界测试:页码超出范围
print("\n页码超出范围测试:")
overflow = paginate(products, page=100, page_size=5)
print(f" 请求第 100 页,实际返回第 {overflow['page']} 页")
print()
# ========================================
# 第五步:用户登录验证函数
# ========================================
def login(username, password):
"""
验证用户登录
参数:
username: 用户名
password: 密码
返回:
登录结果字典,包含 success、message、user
"""
# 检查用户名和密码是否为空
if not username:
return {"success": False, "message": "请输入用户名", "user": None}
if not password:
return {"success": False, "message": "请输入密码", "user": None}
# 查找用户
for user in users:
if user["username"] == username:
if user["password"] == password:
# 登录成功,返回用户信息(不包含密码)
safe_user = {
"id": user["id"],
"username": user["username"],
"nickname": user["nickname"],
"role": user["role"]
}
return {"success": True, "message": "登录成功", "user": safe_user}
else:
return {"success": False, "message": "密码错误", "user": None}
return {"success": False, "message": "用户不存在", "user": None}
# 测试登录函数
print("【用户登录】")
print("-" * 60)
test_cases = [
("admin", "admin123", "正确账号密码"),
("admin", "wrong", "密码错误"),
("nobody", "123456", "用户不存在"),
("", "123456", "用户名为空"),
("admin", "", "密码为空"),
]
for username, password, desc in test_cases:
result = login(username, password)
status = "✅ 通过" if result["success"] else "❌ 失败"
print(f" {desc}:{status} - {result['message']}")
print()
# ========================================
# 第六步:购物车函数
# ========================================
# 购物车数据(内存中维护,程序结束后清空)
cart = []
def add_to_cart(product_id, quantity=1):
"""
将商品添加到购物车
参数:
product_id: 商品 ID
quantity: 数量(默认 1)
返回:
操作结果字典
"""
product = get_product_by_id(product_id)
if product is None:
return {"success": False, "message": f"商品 ID={product_id} 不存在"}
if product["stock"] < quantity:
return {"success": False, "message": f"{product['name']} 库存不足(剩余 {product['stock']})"}
# 检查购物车中是否已有该商品
for item in cart:
if item["product_id"] == product_id:
item["quantity"] += quantity
item["subtotal"] = item["price"] * item["quantity"]
return {"success": True, "message": f"{product['name']} 数量更新为 {item['quantity']}"}
# 新商品,加入购物车
cart.append({
"product_id": product_id,
"name": product["name"],
"price": product["price"],
"quantity": quantity,
"subtotal": product["price"] * quantity
})
return {"success": True, "message": f"{product['name']} 已加入购物车"}
def remove_from_cart(product_id):
"""
从购物车中移除商品
参数:
product_id: 商品 ID
返回:
操作结果字典
"""
for i, item in enumerate(cart):
if item["product_id"] == product_id:
removed = cart.pop(i)
return {"success": True, "message": f"{removed['name']} 已从购物车移除"}
return {"success": False, "message": f"购物车中没有 ID={product_id} 的商品"}
def update_cart_quantity(product_id, quantity):
"""
修改购物车中商品的数量
参数:
product_id: 商品 ID
quantity: 新数量(设为 0 则删除)
返回:
操作结果字典
"""
if quantity <= 0:
return remove_from_cart(product_id)
for item in cart:
if item["product_id"] == product_id:
item["quantity"] = quantity
item["subtotal"] = item["price"] * quantity
return {"success": True, "message": f"{item['name']} 数量更新为 {quantity}"}
return {"success": False, "message": f"购物车中没有 ID={product_id} 的商品"}
def get_cart_summary():
"""
获取购物车摘要
返回:
包含商品列表、总数量、总价格的字典
"""
total_items = 0
total_price = 0
for item in cart:
total_items += item["quantity"]
total_price += item["subtotal"]
return {
"items": cart,
"total_items": total_items,
"total_price": total_price,
"item_count": len(cart)
}
def clear_cart():
"""清空购物车"""
cart.clear()
return {"success": True, "message": "购物车已清空"}
def print_cart():
"""美观地打印购物车内容"""
summary = get_cart_summary()
if summary["item_count"] == 0:
print(" 购物车是空的")
return
for item in summary["items"]:
print(f" - {item['name']} ¥{item['price']} × {item['quantity']} = ¥{item['subtotal']}")
print(f" {'—' * 40}")
print(f" 共 {summary['total_items']} 件,合计 ¥{summary['total_price']}")
# 测试购物车函数
print("【购物车功能】")
print("-" * 60)
print("\n1. 添加商品到购物车:")
result = add_to_cart(1, 1) # iPhone 15 Pro × 1
print(f" {result['message']}")
result = add_to_cart(5, 2) # MacBook Pro 14 × 2
print(f" {result['message']}")
result = add_to_cart(11, 1) # AirPods Pro 2 × 1
print(f" {result['message']}")
print("\n2. 当前购物车:")
print_cart()
print("\n3. 再次添加同一商品(数量应该累加):")
result = add_to_cart(1, 2)
print(f" {result['message']}")
print("\n4. 修改商品数量:")
result = update_cart_quantity(5, 1)
print(f" {result['message']}")
print("\n5. 删除一个商品:")
result = remove_from_cart(11)
print(f" {result['message']}")
print("\n6. 最终购物车:")
print_cart()
print("\n7. 测试异常情况:")
result = add_to_cart(999, 1)
print(f" 添加不存在的商品:{result['message']}")
result = add_to_cart(1, 99999)
print(f" 库存不足时添加:{result['message']}")
print()
# ========================================
# 第七步:用列表推导式重写部分函数
# ========================================
print("【列表推导式 vs 普通写法对比】")
print("-" * 60)
# 对比 1:获取所有商品名
# 普通写法
names_normal = []
for p in products:
names_normal.append(p["name"])
# 列表推导式
names_short = [p["name"] for p in products]
print(f"\n普通写法:{names_normal}")
print(f"列表推导式:{names_short}")
print(f"结果相同:{names_normal == names_short}")
# 对比 2:筛选手机
# 普通写法
phones_normal = []
for p in products:
if p["category"] == "手机":
phones_normal.append(p["name"])
# 列表推导式
phones_short = [p["name"] for p in products if p["category"] == "手机"]
print(f"\n手机(普通写法):{phones_normal}")
print(f"手机(列表推导式):{phones_short}")
print(f"结果相同:{phones_normal == phones_short}")
# 对比 3:格式化输出
summaries = [f"{p['name']}(¥{p['price']})" for p in products if p["price"] > 8000]
print(f"\n价格超过 ¥8000 的商品:{summaries}")
print()
# ========================================
# 总结统计
# ========================================
print("=" * 60)
print("本次编写了以下函数:")
print("=" * 60)
functions = [
("load_json(filename)", "加载 JSON 数据文件"),
("get_product_by_id(product_id)", "根据 ID 查询商品"),
("get_products_by_category(category)", "按分类筛选商品"),
("get_new_products()", "获取所有新品"),
("get_products_by_price_range(min, max)", "按价格区间筛选"),
("search_products(keyword)", "模糊搜索商品"),
("highlight_keyword(text, keyword)", "关键词高亮"),
("paginate(data, page, page_size)", "数据分页"),
("print_pagination(result)", "打印分页结果"),
("login(username, password)", "用户登录验证"),
("add_to_cart(product_id, quantity)", "添加到购物车"),
("remove_from_cart(product_id)", "从购物车移除"),
("update_cart_quantity(product_id, qty)", "修改购物车数量"),
("get_cart_summary()", "获取购物车摘要"),
("clear_cart()", "清空购物车"),
("print_cart()", "打印购物车"),
]
for func_name, desc in functions:
print(f" {func_name:<45} # {desc}")
print(f"\n共 {len(functions)} 个函数,覆盖了商品查询、搜索、分页、用户登录、购物车五大模块。")
运行脚本
python mall_functions.py
完整输出
加载完成:15 个商品,3 个用户,4 个分类
============================================================
【商品查询】
------------------------------------------------------------
ID=1 的商品:iPhone 15 Pro(¥8999)
ID=999 的商品:None
手机分类共 4 个商品:
- iPhone 15 Pro(¥8999)
- iPhone 15(¥5999)
- 华为 Mate 60 Pro(¥6999)
- 小米 14 Pro(¥4999)
新品共 6 个:
- iPhone 15 Pro(¥8999)
- iPhone 15(¥5999)
- 华为 Mate 60 Pro(¥6999)
- MacBook Pro 14(¥14999)
- 华为 MatePad Pro(¥3999)
- Apple Watch Series 9(¥3299)
¥2000 以下的商品共 3 个:
- AirPods Pro 2(¥1899)
- MagSafe 充电器(¥399)
- USB-C 转接头(¥199)
【商品搜索】
------------------------------------------------------------
搜索 'Pro',找到 5 个结果:
- iPhone 【Pro】(¥8999)
- MacBook 【Pro】 14(¥14999)
- iPad 【Pro】 12.9(¥8999)
- AirPods 【Pro】 2(¥1899)
- 华为 MatePad 【Pro】(¥3999)
搜索 '芯片',找到 4 个结果:
- iPhone 15 Pro:A17 【Pro】 芯片,钛金属设计,48MP 主摄
- iPhone 15:A16 【芯片】,灵动岛设计,USB-C 接口
- 华为 Mate 60 Pro:麒麟 9000S,卫星通信,XMAGE 影像
- MacBook Pro 14:M3 Pro 【芯片】,18 小时续航,Liquid Retina XDR
搜索 '不存在的商品xyz',找到 0 个结果
【分页功能】
------------------------------------------------------------
全部商品,第 1 页(每页 5 条):
总计:15 条
页码:第 1/3 页
本页:5 条
- iPhone 15 Pro(¥8999)
- iPhone 15(¥5999)
- 华为 Mate 60 Pro(¥6999)
- 小米 14 Pro(¥4999)
- MacBook Pro 14(¥14999)
全部商品,第 2 页:
总计:15 条
页码:第 2/3 页
本页:5 条
- ThinkPad X1 Carbon(¥9999)
- 华为 MateBook X Pro(¥8999)
- iPad Pro 12.9(¥8999)
- iPad Air(¥4799)
- 华为 MatePad Pro(¥3999)
全部商品,第 3 页:
总计:15 条
页码:第 3/3 页
本页:5 条
- AirPods Pro 2(¥1899)
- Apple Watch Series 9(¥3299)
- MagSafe 充电器(¥399)
- USB-C 转接头(¥199)
- 笔记本支架(¥299)
手机分类,第 1 页(每页 2 条):
总计:4 条
页码:第 1/2 页
本页:2 条
- iPhone 15 Pro(¥8999)
- iPhone 15(¥5999)
页码超出范围测试:
请求第 100 页,实际返回第 3 页
【用户登录】
------------------------------------------------------------
正确账号密码:✅ 通过 - 登录成功
密码错误:❌ 失败 - 密码错误
用户不存在:❌ 失败 - 用户不存在
用户名为空:❌ 失败 - 请输入用户名
密码为空:❌ 失败 - 请输入密码
【购物车功能】
------------------------------------------------------------
1. 添加商品到购物车:
iPhone 15 Pro 已加入购物车
MacBook Pro 14 已加入购物车
AirPods Pro 2 已加入购物车
2. 当前购物车:
- iPhone 15 Pro ¥8999 × 1 = ¥8999
- MacBook Pro 14 ¥14999 × 2 = ¥29998
- AirPods Pro 2 ¥1899 × 1 = ¥1899
————————————————————————————————————————
共 4 件,合计 ¥40896
3. 再次添加同一商品(数量应该累加):
iPhone 15 Pro 数量更新为 3
4. 修改商品数量:
MacBook Pro 14 数量更新为 1
5. 删除一个商品:
AirPods Pro 2 已从购物车移除
6. 最终购物车:
- iPhone 15 Pro ¥8999 × 3 = ¥26997
- MacBook Pro 14 ¥14999 × 1 = ¥14999
————————————————————————————————————————
共 4 件,合计 ¥41996
7. 测试异常情况:
添加不存在的商品:商品 ID=999 不存在
库存不足时添加:iPhone 15 Pro 库存不足(剩余 100)
【列表推导式 vs 普通写法对比】
------------------------------------------------------------
普通写法:['iPhone 15 Pro', 'iPhone 15', '华为 Mate 60 Pro', '小米 14 Pro', 'MacBook Pro 14', 'ThinkPad X1 Carbon', '华为 MateBook X Pro', 'iPad Pro 12.9', 'iPad Air', '华为 MatePad Pro', 'AirPods Pro 2', 'Apple Watch Series 9', 'MagSafe 充电器', 'USB-C 转接头', '笔记本支架']
列表推导式:['iPhone 15 Pro', 'iPhone 15', '华为 Mate 60 Pro', '小米 14 Pro', 'MacBook Pro 14', 'ThinkPad X1 Carbon', '华为 MateBook X Pro', 'iPad Pro 12.9', 'iPad Air', '华为 MatePad Pro', 'AirPods Pro 2', 'Apple Watch Series 9', 'MagSafe 充电器', 'USB-C 转接头', '笔记本支架']
结果相同:True
手机(普通写法):['iPhone 15 Pro', 'iPhone 15', '华为 Mate 60 Pro', '小米 14 Pro']
手机(列表推导式):['iPhone 15 Pro', 'iPhone 15', '华为 Mate 60 Pro', '小米 14 Pro']
结果相同:True
价格超过 ¥8000 的商品:['iPhone 15 Pro(¥8999)', 'MacBook Pro 14(¥14999)', '华为 MateBook X Pro(¥8999)', 'iPad Pro 12.9(¥8999)']
============================================================
本次编写了以下函数:
============================================================
load_json(filename) # 加载 JSON 数据文件
get_product_by_id(product_id) # 根据 ID 查询商品
get_products_by_category(category) # 按分类筛选商品
get_new_products() # 获取所有新品
get_products_by_price_range(min, max) # 按价格区间筛选
search_products(keyword) # 模糊搜索商品
highlight_keyword(text, keyword) # 关键词高亮
paginate(data, page, page_size) # 数据分页
print_pagination(result) # 打印分页结果
login(username, password) # 用户登录验证
add_to_cart(product_id, quantity) # 添加到购物车
remove_from_cart(product_id) # 从购物车移除
update_cart_quantity(product_id, qty) # 修改购物车数量
get_cart_summary() # 获取购物车摘要
clear_cart() # 清空购物车
print_cart() # 打印购物车
共 16 个函数,覆盖了商品查询、搜索、分页、用户登录、购物车五大模块。
六、代码中用到的知识点回顾
在 mall_functions.py 中,每个 Python 知识点都有对应的实际应用:
| 知识点 | 在代码中的应用 |
|---|---|
| if/elif/else | login() 中判断用户名密码是否为空、是否匹配 |
| for 循环 | get_product_by_id() 中遍历商品列表查找匹配项 |
| while 循环 | 分页的 paginate() 中计算总页数 |
| break | 搜索到第一个匹配就停止 |
| continue | 跳过不匹配的商品 |
| range() | paginate() 中计算起止位置 |
| enumerate() | 打印带序号的商品列表 |
| 列表推导式 | 筛选手机、获取商品名列表 |
| 函数定义 | 全部 16 个函数 |
| 参数(默认值) | add_to_cart(product_id, quantity=1) |
| 返回值 | 每个函数返回结果字典 |
| 字典操作 | cart.append()、cart.pop() |
| in 关键字 | keyword in p["name"] 判断是否包含 |
| not / and / or | 多条件组合判断 |
| f-string | 格式化输出商品信息 |
| 异常边界处理 | 页码超出范围自动修正 |
七、课后练习
练习 1:添加按评分排序的函数
def get_top_rated_products(top_n=3):
"""
获取评分最高的 N 个商品
参数:
top_n: 返回数量(默认 3)
返回:
评分从高到低排序的商品列表
"""
sorted_products = sorted(products, key=lambda p: p["rating"], reverse=True)
return sorted_products[:top_n]
top3 = get_top_rated_products(3)
print("评分 Top 3:")
for p in top3:
print(f" - {p['name']}({p['rating']} 分)")
提示:sorted() 是 Python 内置的排序函数,key=lambda p: p["rating"] 表示按 rating 字段排序,reverse=True 表示从高到低。
练习 2:添加库存预警函数
def get_low_stock_products(threshold=50):
"""获取库存低于阈值的商品"""
return [p for p in products if p["stock"] < threshold]
low_stock = get_low_stock_products(60)
print(f"库存低于 60 的商品:{len(low_stock)} 个")
for p in low_stock:
print(f" ⚠️ {p['name']} - 仅剩 {p['stock']} 件")
练习 3:添加购物车商品数量统计
def get_cart_category_stats():
"""统计购物车中各分类的商品数量和金额"""
stats = {}
for item in cart:
product = get_product_by_id(item["product_id"])
cat = product["category"]
if cat not in stats:
stats[cat] = {"count": 0, "total": 0}
stats[cat]["count"] += item["quantity"]
stats[cat]["total"] += item["subtotal"]
return stats
八、今日成果总结
今天完成了什么:
- 学会了 if/elif/else 条件判断
- 学会了 for/while 循环、break、continue
- 学会了列表推导式
- 学会了函数的定义、参数、返回值
- 编写了 16 个 MallLite 核心业务函数
- 覆盖了商品查询、搜索、分页、登录、购物车五大模块
当前项目结构:
mall-lite/
├── data/
│ ├── products.json ← 15 个商品
│ ├── categories.json ← 4 个分类
│ └── users.json ← 3 个用户
├── generate_data.py ← P01:数据生成脚本
├── mall_functions.py ← P02:核心业务函数(本篇)
├── hello.py
└── venv/
九、下篇预告
P03 - 数据结构与常用操作
下一篇将深入讲解列表、字典、元组、集合的高级操作,以及字符串的更多技巧。然后用这些知识为 MallLite 编写订单管理函数和数据统计模块。P03 的数据结构知识是后续接口自动化中解析 JSON 响应的基础。
系列导航
| 序号 | 标题 | 状态 |
|---|---|---|
| P01 | Python 环境搭建与第一行代码 | ✅ 已发布 |
| P02 | 流程控制与函数 | ✅ 本文 |
| P03 | 数据结构与常用操作 | 下一篇 |
| P04 | 文件操作与异常处理 | 待更新 |
| P05 | 面向对象与模块 | 待更新 |
| P06 | 自动化测试常用技巧 | 待更新 |
| 01 | Web UI 自动化项目总览与环境搭建 | 待更新 |
| 02 | 框架基础层搭建 | 待更新 |
更多推荐




所有评论(0)