• 时长: 90 分钟
  • 教学目标:
    • 全面复习和综合运用本系列课程所有核心知识点,包括:变量、数据类型、列表、字典、元组、集合、函数(参数、返回值)、循环(for, while)、条件判断(if-elif-else)、文件操作(读写文本/CSV)、错误处理(try-except)、常用模块(random, os, csv, collections.Counter 等)。
    • 挑战更复杂的项目需求,提升问题分析、系统设计和模块化编程的能力。
    • 学习如何让程序更加灵活和智能,例如加入随机性、更复杂的文件操作、更详细的报告输出。
    • 鼓励学生自主思考和解决问题,培养项目管理和调试技能。
    • 体验构建一个较完整“小工具”的成就感,为后续更深入学习打下坚实基础。

核心项目:“我的智能学习伙伴”——单词记忆小助手

这是一个能让学生复习英文单词,并记录学习情况的程序。

课程内容

1. 复习与引入 (10 分钟)

  • 复习: 快速回顾前一节课的 CSV 文件处理和 collections.Counter。强调这些工具在处理表格数据和统计时的强大之处。
  • 提出问题: 老师提问:“我们已经学到了很多 Python 的强大功能,可以做文件管理、数据统计、小游戏。现在,我们来做一个更有趣、更贴近学习生活的小工具:一个能帮助我们学习和记忆英文单词的助手!它能随机出题,记录对错,还能统计我的学习进度。这需要我们把学过的所有技能都用上!”
  • 引出大型综合项目: 今天的目标是实现一个“单词记忆小助手”,这将是对大家学习成果的一次大检阅和实战挑战。

2. 项目需求分析与系统设计 (15 分钟)

  • 功能需求:
    • 加载单词库: 从一个 CSV 文件(例如 words.csv)加载单词(英文单词, 中文释义)。
    • 单词测试:
      • 随机抽取一个单词进行测试。
      • 显示英文单词,让用户输入中文释义。
      • 判断用户答案是否正确,并给出提示。
      • 记录答对或答错的次数。
    • 学习报告:
      • 显示总共测试了多少个单词。
      • 显示答对和答错的单词数量及正确率。
      • 可以显示哪些单词最容易出错(答错次数最多)。
    • 用户交互菜单: 提供选择(开始测试、查看报告、退出)。
    • 数据持久化: 测试数据(每个单词的答对/答错次数)能保存到文件,下次启动程序时能加载。
    • 错误处理: 处理文件不存在、用户输入无效等情况。
  • 数据存储设计:
    • 单词库: 使用 CSV 文件 words.csv。每行 英文单词,中文释义
      apple,苹果
      banana,香蕉
      cat,猫
      dog,狗
      book,书
      computer,电脑
      ...
      
    • 学习记录: 使用另一个 CSV 文件 study_log.csv。每行 英文单词,答对次数,答错次数
      apple,5,2
      cat,3,1
      ...
      
    • 内存中的数据结构:
      • 单词库:列表,每个元素是字典 {"english": "apple", "chinese": "苹果"}
      • 学习记录:字典,键是英文单词,值是另一个字典 {"correct": 5, "wrong": 2}。例如:{"apple": {"correct": 5, "wrong": 2}, "cat": {"correct": 3, "wrong": 1}}
  • 功能模块分解 (函数设计):
    • load_word_bank(filename): 加载单词库,返回列表。
    • load_study_log(filename): 加载学习记录,返回字典。
    • save_study_log(study_data, filename): 保存学习记录到文件。
    • display_main_menu(): 显示主菜单。
    • start_test(word_bank, study_data): 开始单词测试的核心逻辑。
    • show_report(study_data): 显示学习报告。
    • main_program(): 主程序循环,管理整个系统。

3. Step by Step 实现项目代码 (40 分钟)

老师带领学生一步一步编写代码。这是一个较大的项目,可以根据时间选择重点部分进行讲解和编码。

  • 准备工作和全局常量/变量:
    import csv
    import random
    from collections import Counter # 用于统计错误次数最多的单词
    import os # 用于检查文件是否存在
    
    WORD_BANK_FILE = "words.csv"
    STUDY_LOG_FILE = "study_log.csv"
    
    # 全局变量,用于存储加载的数据
    word_bank = [] # 列表,存储所有单词字典
    study_log = {} # 字典,存储每个单词的学习记录
    
  • 第一步:加载单词库 (load_word_bank)
    • 使用 csv.DictReader 读取 words.csv
    • 处理 FileNotFoundError
    def load_word_bank(filename):
        words = []
        try:
            with open(filename, 'r', encoding='utf-8', newline='') as csvfile:
                reader = csv.DictReader(csvfile)
                for row in reader:
                    if 'english' in row and 'chinese' in row: # 确保包含必要字段
                        words.append({"english": row['english'].strip(), "chinese": row['chinese'].strip()})
                    else:
                        print(f"警告:跳过单词库中格式不正确的行: {row}")
        except FileNotFoundError:
            print(f"错误:单词库文件 '{filename}' 不存在。请确保该文件在程序同目录下。")
            print("请创建该文件,每行包含 'english,chinese'。")
        except Exception as e:
            print(f"加载单词库时发生未知错误: {e}")
        return words
    
  • 第二步:加载和保存学习记录 (load_study_log, save_study_log)
    • load_study_log: 读取 study_log.csv,将答对答错次数转换为整数。
    • save_study_log: 使用 csv.DictWriterstudy_log 字典转换为列表形式保存。
    def load_study_log(filename):
        log = {} # 键是英文单词,值是 {'correct': count, 'wrong': count}
        try:
            with open(filename, 'r', encoding='utf-8', newline='') as csvfile:
                reader = csv.DictReader(csvfile)
                for row in reader:
                    if 'english' in row and 'correct' in row and 'wrong' in row:
                        try:
                            log[row['english']] = {
                                'correct': int(row['correct']),
                                'wrong': int(row['wrong'])
                            }
                        except ValueError:
                            print(f"警告:跳过日志文件中无效的数字行: {row}")
        except FileNotFoundError:
            print(f"学习日志文件 '{filename}' 不存在,将创建新的日志。")
        except Exception as e:
            print(f"加载学习日志时发生未知错误: {e}")
        return log
    
    def save_study_log(study_data, filename):
        # 准备写入 CSV 的数据格式
        log_rows = []
        for english_word, counts in study_data.items():
            log_rows.append({
                'english': english_word,
                'correct': counts['correct'],
                'wrong': counts['wrong']
            })
    
        fieldnames = ['english', 'correct', 'wrong']
        with open(filename, 'w', encoding='utf-8', newline='') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            writer.writeheader()
            writer.writerows(log_rows)
        print("学习记录已保存。")
    
  • 第三步:显示主菜单 (display_main_menu)
    def display_main_menu():
        print("\n--- 单词记忆小助手 ---")
        print("1. 开始单词测试")
        print("2. 查看学习报告")
        print("0. 退出系统")
        print("--------------------")
    
  • 第四步:单词测试核心逻辑 (start_test)
    • word_bank 随机抽取单词 (random.choice)。
    • 循环进行测试 (while 循环,或设定测试题目数量的 for 循环)。
    • 获取用户输入,判断对错 (if-else)。
    • 更新 study_log 字典中的答对/答错次数。
    def start_test(word_bank_list, study_log_dict):
        if not word_bank_list:
            print("单词库为空,无法开始测试。请检查 'words.csv' 文件。")
            return
    
        print("\n--- 单词测试开始 (输入 'quit' 结束) ---")
        tested_count = 0
        correct_count = 0
    
        while True:
            # 随机选择一个单词
            word_to_test = random.choice(word_bank_list)
            english = word_to_test['english']
            chinese_correct = word_to_test['chinese']
    
            # 获取用户输入
            user_answer = input(f"请写出 '{english}' 的中文释义 (输入 'quit' 退出): ").strip()
    
            if user_answer.lower() == 'quit':
                break # 退出测试循环
    
            tested_count += 1
    
            # 初始化该单词的记录 (如果第一次测试)
            if english not in study_log_dict:
                study_log_dict[english] = {'correct': 0, 'wrong': 0}
    
            # 判断答案
            if user_answer == chinese_correct:
                print("✅ 回答正确!")
                study_log_dict[english]['correct'] += 1
                correct_count += 1
            else:
                print(f"❌ 回答错误。正确答案是:'{chinese_correct}'")
                study_log_dict[english]['wrong'] += 1
            print("-" * 20)
    
        print(f"\n--- 测试结束 ---")
        if tested_count > 0:
            print(f"总共测试了 {tested_count} 个单词。")
            print(f"答对 {correct_count} 个,答错 {tested_count - correct_count} 个。")
            print(f"正确率: {(correct_count / tested_count * 100):.2f}%")
        else:
            print("本次测试没有完成任何单词。")
    
  • 第五步:显示学习报告 (show_report)
    • 遍历 study_log 字典,计算总测试数、总对错数。
    • 利用 collections.Counter 找出最容易出错的单词(按 wrong 次数排序)。
    def show_report(study_log_dict):
        print("\n--- 学习报告 ---")
        if not study_log_dict:
            print("还没有学习记录。请先进行测试。")
            return
    
        total_tested = 0
        total_correct = 0
        total_wrong = 0
        wrong_counts = Counter() # 用 Counter 统计每个单词的错误次数
    
        for english_word, counts in study_log_dict.items():
            current_correct = counts.get('correct', 0)
            current_wrong = counts.get('wrong', 0)
    
            total_tested += (current_correct + current_wrong)
            total_correct += current_correct
            total_wrong += current_wrong
            wrong_counts[english_word] = current_wrong # 记录错误次数
    
        print(f"总计测试单词数: {total_tested}")
        print(f"总计答对数: {total_correct}")
        print(f"总计答错数: {total_wrong}")
    
        if total_tested > 0:
            accuracy = (total_correct / total_tested) * 100
            print(f"总正确率: {accuracy:.2f}%")
        else:
            print("尚无有效的测试记录。")
    
        print("\n--- 最容易出错的单词 (按错误次数从多到少) ---")
        most_common_wrong = wrong_counts.most_common(5) # 找出错误次数最多的5个
        if most_common_wrong:
            for word, count in most_common_wrong:
                if count > 0: # 只显示有错误的
                    print(f"'{word}': 错了 {count} 次")
        else:
            print("太棒了,目前没有答错记录!")
        print("--------------------")
    
  • 第六步:主程序循环 (main_program)
    • 加载数据,显示菜单,处理用户选择,退出时保存数据。
    def main_program():
        global word_bank # 声明使用全局变量
        global study_log
    
        # 1. 程序启动时,加载数据
        word_bank = load_word_bank(WORD_BANK_FILE)
        study_log = load_study_log(STUDY_LOG_FILE)
    
        if not word_bank:
            print("警告:单词库为空,请确保 'words.csv' 文件内容正确。")
            # 可以选择在这里退出,或者让用户创建单词
            # return
    
        while True:
            display_main_menu()
            choice = input("请选择操作 (输入数字): ").strip()
    
            if choice == '1':
                start_test(word_bank, study_log)
            elif choice == '2':
                show_report(study_log)
            elif choice == '0':
                print("正在保存学习记录并退出系统...")
                save_study_log(study_log, STUDY_LOG_FILE)
                print("感谢使用,下次再见!")
                break
            else:
                print("无效的选择,请重新输入。")
    
    # 程序启动入口
    if __name__ == "__main__":
        # 为了方便调试,可以在这里创建一些初始文件
        if not os.path.exists(WORD_BANK_FILE):
            print(f"正在创建示例单词库文件: {WORD_BANK_FILE}")
            with open(WORD_BANK_FILE, 'w', encoding='utf-8', newline='') as f:
                writer = csv.writer(f)
                writer.writerow(['english', 'chinese']) # 写入表头
                writer.writerow(['apple', '苹果'])
                writer.writerow(['banana', '香蕉'])
                writer.writerow(['computer', '电脑'])
                writer.writerow(['book', '书'])
                writer.writerow(['hello', '你好'])
                writer.writerow(['world', '世界'])
                writer.writerow(['python', '派森'])
                writer.writerow(['programming', '编程'])
                writer.writerow(['science', '科学'])
                writer.writerow(['mathematics', '数学'])
        else:
            print(f"找到单词库文件: {WORD_BANK_FILE}")
    
        main_program()
    

    (强调 global 关键字的使用,让函数能修改全局变量。)

4. 课堂巩固练习与扩展 (15 分钟)

  • 练习 1: 增加一个功能:添加新单词到单词库。
    • 在主菜单中增加一个选项(例如 3. 添加新单词)。
    • 编写一个函数 add_new_word(word_bank_list, filename),让用户输入英文单词和中文释义。
    • 检查单词是否已存在于单词库。
    • 如果不存在,添加到 word_bank_list,并更新 words.csv 文件。
  • 练习 2:start_test 函数中,增加一个选项,让用户选择一次测试多少个单词,而不是无限循环。
  • 练习 3: (选做) 优化 show_report 函数,除了显示最容易出错的单词,还可以显示正确率最高的 3 个单词。

5. 总结与提问 (5 分钟)

  • 回顾: 总结本节课通过“单词记忆小助手”项目,全面综合运用了:列表和字典组织数据,CSV 文件读写持久化,函数封装模块,random 模块随机出题,循环和条件判断控制流程,collections.Counter 统计报告,以及错误处理。强调了系统设计和分解问题的过程。
  • 提问:
    • 在这个项目中,哪个数据结构用来存储所有单词?哪个用来存储学习记录?
    • 我们为什么用 CSV 文件来保存数据?
    • start_test 函数中,哪些地方用到了 random 模块?
    • show_report 函数中,collections.Counter 帮我们解决了什么问题?
    • 你觉得这个项目中,哪个功能实现起来最有挑战?
  • 答疑: 回答学生问题。

6. 布置课后作业 (5 分钟)

  • 作业 1: 完善课堂练习 1 和 2 的功能(添加新单词,设置测试题目数量)。
  • 作业 2: 增加一个功能:删除单词。
    • 在主菜单中增加一个选项。
    • 编写一个函数 delete_word(word_bank_list, study_log_dict, filename),让用户输入要删除的英文单词。
    • 如果单词存在,从 word_bank_liststudy_log_dict 中都删除,并更新 words.csv
  • 作业 3: 优化用户体验:在 start_test 中,如果用户回答错误,可以提示用户是否要再尝试一次。
  • 作业 4: (选做) 进一步美化输出,例如使用更多的 f-string 格式化,或者使用简单的文本颜色(需要导入 colorama 模块,如果环境允许)。或者,探索如何将学习记录保存为 JSON 格式,因为它能直接保存字典,比 CSV 更方便处理复杂结构(简单介绍 import jsonjson.dump/json.load)。
  1. 本网站名称:系统驰云
  2. 本站永久网址:https://blog.xxyyo.com
  3. 本网站的内容均来源于网络,仅供大家学习与交流,如有侵权,请联系站长365919529@qq.com删除处理。
  4. 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
  5. 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
  6. 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。365919529@qq.com