19.Python中的标准库练习题

Python 标准库练习题(含答案)

1. random——随机抽奖

题目: 有一个参与抽奖的名单,编写程序:

  1. 随机选出 1 名一等奖得主
  2. 随机选出 3 名二等奖得主(不能和一等奖重复)
  3. 打印结果
participants = ["张三", "李四", "王五", "赵六", "孙七", "周八", "吴九", "郑十"]

参考答案:

import random

participants = ["张三", "李四", "王五", "赵六", "孙七", "周八", "吴九", "郑十"]

# 一等奖:随机选 1 名
first_prize = random.choice(participants)

# 二等奖:从剩余名单中选 3 名(不能重复)
remaining = [p for p in participants if p != first_prize]
second_prizes = random.sample(remaining, 3)

print(f"🥇 一等奖:{first_prize}")
print(f"🥈 二等奖:{second_prizes[0]}、{second_prizes[1]}、{second_prizes[2]}")

关键点:

  • random.choice():从列表随机选 1 个
  • random.sample(列表, k):无放回地随机选 k 个,不会重复

2. random——猜数字游戏

题目: 编写一个猜数字游戏:

  1. 程序随机生成 1~100 之间的整数
  2. 玩家不断输入猜测值
  3. 程序提示”太大了”、”太小了”或”恭喜猜对了!”
  4. 猜对后打印共猜了几次

参考答案:

import random

secret = random.randint(1, 100)
count  = 0

print("我已经想好了一个 1~100 之间的整数,请你来猜!")

while True:
    guess = int(input("请输入你的猜测:"))
    count += 1

    if guess < secret:
        print("太小了,再大一点!")
    elif guess > secret:
        print("太大了,再小一点!")
    else:
        print(f"恭喜你猜对了!答案就是 {secret},你共猜了 {count} 次。")
        break

关键点:

  • random.randint(1, 100):生成 1 到 100 之间的随机整数(包含两端)
  • while True + break:无限循环直到猜对为止

3. datetime——日期格式转换

题目: 把下面的日期字符串统一转换成 "YYYY年MM月DD日" 的格式,并打印出来:

dates = [
    "2024-01-15",
    "2023-12-31",
    "2025-07-04",
]

参考答案:

from datetime import datetime

dates = [
    "2024-01-15",
    "2023-12-31",
    "2025-07-04",
]

for date_str in dates:
    # 先解析成 datetime 对象
    dt = datetime.strptime(date_str, "%Y-%m-%d")
    # 再格式化成目标格式
    formatted = dt.strftime("%Y年%m月%d日")
    print(formatted)

# 输出:
# 2024年01月15日
# 2023年12月31日
# 2025年07月04日

关键点:

  • strptime(字符串, 格式):字符串 → datetime 对象(parse)
  • strftime(格式):datetime 对象 → 字符串(format)

4. datetime——倒计时计算

题目: 编写程序,计算距离某个重要日期还有多少天。例如计算距离 2026 年元旦(2026-01-01)还有多少天,并格式化打印当前日期。

参考答案:

from datetime import date

today    = date.today()
new_year = date(2026, 1, 1)

diff = new_year - today
days_left = diff.days

print(f"今天是:{today.strftime('%Y年%m月%d日')}")

if days_left > 0:
    print(f"距离 2026 年元旦还有 {days_left} 天!")
elif days_left == 0:
    print("今天就是 2026 年元旦!新年快乐!")
else:
    print(f"2026 年元旦已经过去 {abs(days_left)} 天了。")

关键点:

  • date.today():获取今天的日期
  • 两个 date 对象相减,得到 timedelta 对象,.days 取天数
  • diff.days 可能为负(目标日期已过)

5. os / pathlib——文件信息统计

题目: 编写程序,统计当前目录下(不含子目录)所有 .md 文件的数量和文件名,打印出来。使用 pathlib 实现。

参考答案:

from pathlib import Path

current_dir = Path(".")   # 当前目录

md_files = [f for f in current_dir.iterdir() if f.suffix == ".md" and f.is_file()]

print(f"当前目录下共有 {len(md_files)} 个 .md 文件:")
for f in sorted(md_files):
    print(f"  {f.name}")

进阶版(包含子目录,用 rglob 递归查找):

from pathlib import Path

all_md = list(Path(".").rglob("*.md"))   # 递归查找所有 .md 文件

print(f"共找到 {len(all_md)} 个 .md 文件:")
for f in sorted(all_md):
    print(f"  {f}")

关键点:

  • Path(".").iterdir():遍历当前目录(不含子目录)
  • f.suffix:获取文件扩展名(如 .md
  • Path(".").rglob("*.md"):递归查找所有匹配的文件

6. math——几何计算器

题目: 编写一个函数 shape_info(shape, *args),根据图形类型和参数计算面积和周长:

  • circle(圆):传入半径
  • rectangle(矩形):传入宽和高
  • triangle(三角形,已知三边 a、b、c):用海伦公式计算面积

参考答案:

import math

def shape_info(shape, *args):
    if shape == "circle":
        r = args[0]
        area      = math.pi * r ** 2
        perimeter = 2 * math.pi * r
        print(f"圆(半径={r}):面积={area:.4f},周长={perimeter:.4f}")

    elif shape == "rectangle":
        w, h = args[0], args[1]
        area      = w * h
        perimeter = 2 * (w + h)
        print(f"矩形({w}×{h}):面积={area:.4f},周长={perimeter:.4f}")

    elif shape == "triangle":
        a, b, c = args[0], args[1], args[2]
        s    = (a + b + c) / 2           # 半周长
        area = math.sqrt(s * (s-a) * (s-b) * (s-c))  # 海伦公式
        perimeter = a + b + c
        print(f"三角形({a},{b},{c}):面积={area:.4f},周长={perimeter:.4f}")

    else:
        print(f"未知图形:{shape}")

shape_info("circle",    5)
shape_info("rectangle", 4, 6)
shape_info("triangle",  3, 4, 5)

输出:

圆(半径=5):面积=78.5398,周长=31.4159
矩形(4×6):面积=24.0000,周长=20.0000
三角形(3,4,5):面积=6.0000,周长=12.0000

关键点: math.sqrt() 求平方根,math.pi 是圆周率常数。


7. json——读写学生成绩

题目: 编写程序完成以下操作:

  1. 把下面的学生成绩数据保存到 scores.json 文件
  2. 再从文件读取回来
  3. 计算每位学生的平均分并打印
students = [
    {"name": "张三", "scores": {"语文": 88, "数学": 92, "英语": 85}},
    {"name": "李四", "scores": {"语文": 75, "数学": 68, "英语": 90}},
    {"name": "王五", "scores": {"语文": 95, "数学": 88, "英语": 79}},
]

参考答案:

import json

students = [
    {"name": "张三", "scores": {"语文": 88, "数学": 92, "英语": 85}},
    {"name": "李四", "scores": {"语文": 75, "数学": 68, "英语": 90}},
    {"name": "王五", "scores": {"语文": 95, "数学": 88, "英语": 79}},
]

# 第一步:写入 JSON 文件
with open("scores.json", "w", encoding="utf-8") as f:
    json.dump(students, f, ensure_ascii=False, indent=2)
print("成绩已保存到 scores.json")

# 第二步:从文件读取
with open("scores.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)

# 第三步:计算平均分并打印
print("n学生成绩报告:")
print("-" * 35)
for student in loaded:
    name   = student["name"]
    scores = student["scores"].values()
    avg    = sum(scores) / len(scores)
    print(f"{name}:各科成绩 {list(student['scores'].values())},平均分 {avg:.1f}")

输出:

成绩已保存到 scores.json

学生成绩报告:
-----------------------------------
张三:各科成绩 [88, 92, 85],平均分 88.3
李四:各科成绩 [75, 68, 90],平均分 77.7
王五:各科成绩 [95, 88, 79],平均分 87.3

关键点:

  • json.dump(数据, 文件对象):写入文件
  • json.load(文件对象):从文件读取
  • ensure_ascii=False:允许中文,indent=2:美化格式

8. collections.Counter——词频统计

题目: 对下面这段文字进行词频统计(按空格分词),找出出现次数最多的 5 个词,打印词和对应的出现次数。

text = """python is great python is easy to learn python is powerful
programming with python is fun python community is large and supportive"""

参考答案:

from collections import Counter

text = """python is great python is easy to learn python is powerful
programming with python is fun python community is large and supportive"""

words   = text.split()          # 按空格分词
counter = Counter(words)        # 统计每个词的出现次数

print("词频统计(前5名):")
for word, count in counter.most_common(5):
    bar = "█" * count           # 用方块直观显示频次
    print(f"  {word:15} {count} 次  {bar}")

输出:

词频统计(前5名):
  python          5 次  █████
  is              5 次  █████
  great           1 次  █
  easy            1 次  █
  to              1 次  █

关键点:

  • Counter(列表):统计列表中各元素的出现次数
  • counter.most_common(n):返回出现次数最多的 n 个元素,格式为 [(元素, 次数), ...]

9. collections.defaultdict——按类型分组

题目: 把下面的商品列表按照类别分组,用 defaultdict 实现,打印每个类别的商品列表。

products = [
    ("苹果",   "水果"),
    ("牛奶",   "饮品"),
    ("香蕉",   "水果"),
    ("橙汁",   "饮品"),
    ("薯片",   "零食"),
    ("草莓",   "水果"),
    ("可乐",   "饮品"),
    ("巧克力", "零食"),
]

参考答案:

from collections import defaultdict

products = [
    ("苹果",   "水果"),
    ("牛奶",   "饮品"),
    ("香蕉",   "水果"),
    ("橙汁",   "饮品"),
    ("薯片",   "零食"),
    ("草莓",   "水果"),
    ("可乐",   "饮品"),
    ("巧克力", "零食"),
]

# defaultdict(list):不存在的键自动初始化为空列表
grouped = defaultdict(list)

for name, category in products:
    grouped[category].append(name)

print("商品分类:")
for category, items in grouped.items():
    print(f"  {category}:{', '.join(items)}")

输出:

商品分类:
  水果:苹果, 香蕉, 草莓
  饮品:牛奶, 橙汁, 可乐
  零食:薯片, 巧克力

关键点: defaultdict(list) 让你直接 grouped[key].append(value) 而不用先检查键是否存在,避免 KeyError


10. re——数据提取

题目: 从下面的文本中,用正则表达式分别提取:

  1. 所有日期(格式:YYYY-MM-DD)
  2. 所有金额(格式:数字 + “元”,如 “1500元”)
  3. 所有邮箱地址
text = """
会议记录:
日期:2024-03-11,地点:北京
参会人:张三(zhangsan@company.com)、李四(lisi@gmail.com)
议题1(2024-03-15 截止):项目预算 50000元,已花费 12800元
议题2(2024-04-01 截止):采购设备 8500元
下次会议:2024-05-20
"""

参考答案:

import re

text = """
会议记录:
日期:2024-03-11,地点:北京
参会人:张三(zhangsan@company.com)、李四(lisi@gmail.com)
议题1(2024-03-15 截止):项目预算 50000元,已花费 12800元
议题2(2024-04-01 截止):采购设备 8500元
下次会议:2024-05-20
"""

# 1. 提取所有日期
dates = re.findall(r"d{4}-d{2}-d{2}", text)
print("日期:", dates)
# ['2024-03-11', '2024-03-15', '2024-04-01', '2024-05-20']

# 2. 提取所有金额
amounts = re.findall(r"d+元", text)
print("金额:", amounts)
# ['50000元', '12800元', '8500元']

# 3. 提取所有邮箱
emails = re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}", text)
print("邮箱:", emails)
# ['zhangsan@company.com', 'lisi@gmail.com']

关键点:

  • re.findall(pattern, text):返回所有匹配的字符串列表
  • d{4}:恰好 4 个数字;d+:1 个或更多数字
  • 正则字符串建议用 r"..." 原始字符串

11. re——数据清洗

题目: 有一批从表单收集来的手机号,格式混乱,请用正则表达式统一清洗成纯数字格式(只保留数字):

raw_phones = [
    "138-1234-5678",
    "(021) 8765-4321",
    "  13987654321  ",
    "010 - 88886666",
    "400 800 1234",
]

参考答案:

import re

raw_phones = [
    "138-1234-5678",
    "(021) 8765-4321",
    "  13987654321  ",
    "010 - 88886666",
    "400 800 1234",
]

print("清洗后的号码:")
for raw in raw_phones:
    # re.sub 把所有非数字字符替换为空字符串
    clean = re.sub(r"D", "", raw)   # D 表示非数字字符
    print(f"  {raw:25} → {clean}")

输出:

清洗后的号码:
  138-1234-5678             → 13812345678
  (021) 8765-4321           → 02187654321
    13987654321             → 13987654321
  010 - 88886666            → 01088886666
  400 800 1234              → 4008001234

关键点:

  • re.sub(pattern, replacement, string):把匹配的部分替换为指定字符串
  • D:匹配任何非数字字符(等同于 [^0-9]

12. time——代码性能对比

题目: 比较下面两种求 1~1000000 之和的方法的运行时间,用 time.perf_counter() 计时:

  1. for 循环累加
  2. 用内置 sum() + range()

参考答案:

import time

N = 1_000_000

# 方法一:for 循环
start = time.perf_counter()
total = 0
for i in range(1, N + 1):
    total += i
end = time.perf_counter()
t1  = end - start
print(f"for 循环:结果={total},耗时={t1:.6f} 秒")

# 方法二:sum() + range()
start = time.perf_counter()
total = sum(range(1, N + 1))
end   = time.perf_counter()
t2    = end - start
print(f"sum():  结果={total},耗时={t2:.6f} 秒")

# 对比
print(f"nsum() 比 for 循环快 {t1 / t2:.1f} 倍")

示例输出:

for 循环:结果=500000500000,耗时=0.045231 秒
sum():  结果=500000500000,耗时=0.008764 秒

sum() 比 for 循环快 5.2 倍

关键点:

  • time.perf_counter() 精度比 time.time() 更高,适合代码计时
  • 内置的 sum() 是用 C 实现的,比纯 Python 的 for 循环快很多

13. itertools——生成彩票号码

题目:itertools.combinations 生成所有可能的彩票号码组合(从 1~10 中选 3 个数字),统计共有多少种组合,并随机抽取一组作为”中奖号码”。

参考答案:

import itertools
import random

numbers = range(1, 11)   # 1 到 10

# 生成所有 C(10, 3) = 120 种组合
all_combinations = list(itertools.combinations(numbers, 3))

print(f"从 1~10 中选 3 个数字,共有 {len(all_combinations)} 种组合")
print(f"前 5 种:{all_combinations[:5]}")

# 随机抽取一组作为中奖号码
winning = random.choice(all_combinations)
print(f"n本期中奖号码:{winning}")

# 让用户也选一组
my_pick = tuple(sorted(random.sample(range(1, 11), 3)))
print(f"你选的号码:{my_pick}")

if my_pick == winning:
    print("恭喜中奖!")
else:
    print(f"很遗憾,没有中奖。中奖号码是 {winning}")

关键点:

  • itertools.combinations(可迭代对象, r):从中选 r 个,不考虑顺序,不重复
  • itertools.permutations:考虑顺序(排列);combinations:不考虑顺序(组合)

14. 综合题——个人日记本(json + datetime + os)

题目: 实现一个简单的命令行日记本:

  1. 每条日记自动记录当前时间
  2. 日记保存在 diary.json 文件中(不存在时自动创建)
  3. 支持两个功能:添加日记、查看所有日记

参考答案:

import json
import os
from datetime import datetime

DIARY_FILE = "diary.json"

def load_diary():
    """加载日记文件,不存在则返回空列表"""
    if not os.path.exists(DIARY_FILE):
        return []
    with open(DIARY_FILE, "r", encoding="utf-8") as f:
        return json.load(f)

def save_diary(entries):
    """保存日记到文件"""
    with open(DIARY_FILE, "w", encoding="utf-8") as f:
        json.dump(entries, f, ensure_ascii=False, indent=2)

def add_entry(content):
    """添加一条日记"""
    entries = load_diary()
    entry = {
        "time":    datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "content": content
    }
    entries.append(entry)
    save_diary(entries)
    print(f"日记已保存!({entry['time']})")

def show_all():
    """显示所有日记"""
    entries = load_diary()
    if not entries:
        print("暂无日记记录。")
        return
    print(f"n=== 我的日记(共 {len(entries)} 条)===")
    for i, entry in enumerate(entries, 1):
        print(f"n【第 {i} 条】{entry['time']}")
        print(f"  {entry['content']}")
    print()

# 测试
add_entry("今天学习了 Python 标准库,感觉收获很多!")
add_entry("用 json 模块实现了日记持久化存储,很有成就感。")
show_all()

运行结果:

日记已保存!(2024-03-11 14:30:25)
日记已保存!(2024-03-11 14:30:25)

=== 我的日记(共 2 条)===

【第 1 条】2024-03-11 14:30:25
  今天学习了 Python 标准库,感觉收获很多!

【第 2 条】2024-03-11 14:30:25
  用 json 模块实现了日记持久化存储,很有成就感。

15. 综合挑战——学生成绩分析系统

题目: 综合运用 randomdatetimejsoncollectionsmath 模块,实现一个学生成绩分析系统:

  1. random 随机生成 10 名学生的三科成绩(语文、数学、英语,每科 60~100 分)
  2. 将成绩数据保存到 students.json
  3. 计算每名学生的平均分
  4. Counter 统计各分数段的人数(60-69、70-79、80-89、90-100)
  5. 找出平均分最高和最低的学生
  6. 打印完整分析报告,并在报告顶部显示生成时间(用 datetime

参考答案:

import random
import json
import math
from datetime import datetime
from collections import Counter

# ① 生成随机成绩数据
names    = ["张三", "李四", "王五", "赵六", "孙七", "周八", "吴九", "郑十", "钱一", "冯二"]
subjects = ["语文", "数学", "英语"]

students = []
for name in names:
    scores = {subject: random.randint(60, 100) for subject in subjects}
    avg    = sum(scores.values()) / len(scores)
    students.append({
        "name":    name,
        "scores":  scores,
        "average": round(avg, 1)
    })

# ② 保存到 JSON 文件
with open("students.json", "w", encoding="utf-8") as f:
    json.dump(students, f, ensure_ascii=False, indent=2)

# ③ 统计分数段
def get_grade(avg):
    if avg >= 90:  return "90-100"
    elif avg >= 80: return "80-89"
    elif avg >= 70: return "70-79"
    else:           return "60-69"

grade_counter = Counter(get_grade(s["average"]) for s in students)

# ④ 找最高/最低
best  = max(students, key=lambda s: s["average"])
worst = min(students, key=lambda s: s["average"])

# ⑤ 打印完整报告
now = datetime.now().strftime("%Y年%m月%d日 %H:%M:%S")
print(f"╔{'═'*42}╗")
print(f"║{'学生成绩分析报告':^40}║")
print(f"║{'生成时间:' + now:^40}║")
print(f"╚{'═'*42}╝")

print(f"n{'姓名':^6} {'语文':^6} {'数学':^6} {'英语':^6} {'平均分':^6}")
print("-" * 38)
for s in sorted(students, key=lambda x: x["average"], reverse=True):
    sc = s["scores"]
    print(f"{s['name']:^6} {sc['语文']:^6} {sc['数学']:^6} {sc['英语']:^6} {s['average']:^6}")

print(f"n分数段分布:")
for grade in ["90-100", "80-89", "70-79", "60-69"]:
    count = grade_counter.get(grade, 0)
    bar   = "■" * count
    print(f"  {grade} 分:{count:2} 人  {bar}")

print(f"n平均分最高:{best['name']}({best['average']} 分)")
print(f"平均分最低:{worst['name']}({worst['average']} 分)")

# 计算全班总平均分(用 math.fsum 精度更高)
all_avgs    = [s["average"] for s in students]
class_avg   = math.fsum(all_avgs) / len(all_avgs)
print(f"全班平均分:{class_avg:.1f} 分")

示例输出:

╔══════════════════════════════════════════╗
║            学生成绩分析报告              ║
║   生成时间:2024年03月11日 14:30:25      ║
╚══════════════════════════════════════════╝

 姓名   语文   数学   英语  平均分
--------------------------------------
 王五    96     91     88    91.7
 张三    88     92     85    88.3
 ...

分数段分布:
  90-100 分: 2 人  ■■
  80-89  分: 5 人  ■■■■■
  70-79  分: 2 人  ■■
  60-69  分: 1 人  ■

平均分最高:王五(91.7 分)
平均分最低:钱一(64.3 分)
全班平均分:80.6 分

涉及知识点:

模块 用途
random.randint 生成随机成绩
json.dump / load 保存和读取成绩文件
datetime.now 报告生成时间
collections.Counter 统计分数段分布
math.fsum 高精度求和

知识点速查

题号 模块 考查点
1 random choicesample 随机抽选
2 random randint + while 循环游戏
3 datetime strptime 解析 + strftime 格式化
4 datetime date.today()、两日期相减、timedelta.days
5 pathlib iterdir()suffixrglob()
6 math sqrtpi、海伦公式
7 json dump/load 读写文件,ensure_ascii
8 collections Counter 词频统计,most_common
9 collections defaultdict(list) 分组
10 re findall 提取日期/金额/邮箱
11 re sub 数据清洗,D 非数字匹配
12 time perf_counter 代码计时对比
13 itertools combinations 生成组合
14 json + datetime + os 命令行日记本综合应用
15 多模块综合 成绩分析系统(random + json + datetime + Counter + math)

发表评论