AI 学院 · Python 入门线 · 节点 ⑨ / ⑨

毕业项目:背单词 CLI

收官之战:独立完成一个真实可用的程序,串联①-⑧全部知识点。约 6-10 个番茄,做出来的工具你自己会用、能放在服务器上长期跑。

状态 进行中 前置 ⑧ 网络与 API 下一步 毕业 → AI 课程主线

第 0 步 · 毕业标准

节点 ⑨ 不做"教程",给你需求 + 设计 + 验收标准,自己动手。完成后你将拥有:一个能长期使用的背单词工具 + 一份"我能独立写程序"的证据。

第 1 步 · 需求(做什么)

一个命令行背单词工具 vocab.py

第 2 步 · 设计(数据怎么组织)

2.1 数据结构

# data/vocab.json —— 词库
{"resilience": {"meaning": "韧性", "tag": "考研"}}

# data/progress.json —— 学习进度
{"resilience": {"correct": 3, "wrong": 1, "last": "2026-08-12", "next": "2026-08-13"}}

2.2 代码结构(函数划分)

vocab.py
├── load_json(path, default)      # 读 JSON(④),不存在返回默认(④)
├── save_json(path, data)       # 写 JSON(④)
├── pick_question(vocab, progress)  # 随机选词与题型(②⑥ random)
├── ask(word, entry, mode)      # 出一道题,返回对错(①)
├── record(progress, word, ok)  # 更新进度 + 定 next 日期(⑥ datetime)
├── do_learn(vocab, progress)   # learn 流程(① 循环)
├── do_review(vocab, progress)  # review 流程(⑥ 按日期筛选)
├── do_stats(vocab, progress)   # 统计(② 字典 + ⑦ 思路)
└── do_export(vocab, progress)  # 导出 CSV(⑦)
先画结构再写码——这就是"设计"。每个函数只干一件事,主程序(main)只负责调度。写到一半卡住时,回来对照这张图。

第 3 步 · 核心代码片段(自己补全其余部分)

3.1 主程序骨架(if __name__ 保护,⑥学的)

import sys, json, random, datetime, csv
from pathlib import Path

DATA = Path("data")

def load_json(name, default):
    """读取 data/name;文件不存在返回 default"""
    p = DATA / name
    if not p.exists():
        return default
    with open(p, "r", encoding="utf-8") as f:
        return json.load(f)

def save_json(name, data):
    DATA.mkdir(exist_ok=True)
    with open(DATA / name, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

def main():
    cmd = sys.argv[1] if len(sys.argv) > 1 else "learn"
    vocab = load_json("vocab.json", SAMPLE)
    progress = load_json("progress.json", {})
    if cmd == "learn":   do_learn(vocab, progress)
    elif cmd == "review": do_review(vocab, progress)
    elif cmd == "stats":  do_stats(vocab, progress)
    elif cmd == "export": do_export(vocab, progress)
    else: print("用法: python vocab.py [learn|review|stats|export]")

if __name__ == "__main__":
    main()

3.2 出一道题(模式随机:英译中 / 中译英 / 拼写)

def ask(word, entry):
    mode = random.choice(["en2zh", "zh2en", "spell"])
    if mode == "en2zh":
        answer = input(f"{word} 的中文是?").strip()
        return answer == entry["meaning"]
    if mode == "zh2en":
        answer = input(f"「{entry['meaning']}」的英文是?").strip().lower()
        return answer == word.lower()
    # spell:显示乱序字母,让用户拼出单词
    letters = list(word); random.shuffle(letters)
    answer = input(f"拼写:{''.join(letters)} ({entry['meaning']})→").strip().lower()
    return answer == word.lower()

3.3 记录进度(答对 3 次 = 学会;答错 → 明天再来)

def record(progress, word, ok):
    p = progress.setdefault(word, {"correct": 0, "wrong": 0, "next": ""})
    if ok:
        p["correct"] += 1
    else:
        p["wrong"] += 1
    p["next"] = (datetime.date.today() + datetime.timedelta(days=1 if ok else 0)).isoformat()
    # 答错:next=今天 → review 立刻再考;答对:明天

第 4 步 · 验收清单(对照自查)

第 5 步 · 复盘:你走过的路

毕业纪念:给这个工具起个名字、写进你的 README、把"第一个自己设计的程序"记进工作日志。代码会过时,但"我能独立造工具"的信心不会。

推荐资料(毕业后按需)