有趣的python程序Part1:如何根据记忆曲线使用python编写一个单词记忆默写程序

发布于:2025-06-19 ⋅ 阅读:(16) ⋅ 点赞:(0)

目录

前言

1. 数据管理模块

 2. 记忆算法实现

3. 持久化存储

 4. 用户界面实现

5.整合与测试


前言

        此篇文章为“有趣的python程序”专栏的第一篇文章,本专栏致力于分享一些有趣的编程作品,如果能够使您产生兴趣,不妨来动手改编使之成为更好的工具吧!若是能够帮助到您,在下不胜荣幸!

我们先来确定一下单词记忆程序的功能框架,它需要具有以下功能:

- 基于记忆曲线(艾宾浩斯遗忘曲线)安排单词复习
- 记录用户对单词的掌握情况
- 提供学习和测试两种模式
- 持久化保存学习数据


故此我们可以将程序分为几个核心部分:
- **数据管理**:存储单词及其记忆状态
- **记忆算法**:计算下次复习时间
- **用户界面**:与用户交互的界面
- **持久化存储**:保存学习进度

## 第二阶段:分模块实现

1. 数据管理模块

先来看以下代码:

import datetime
from collections import defaultdict

class WordMemorySystem:
    def __init__(self):
        # 使用字典存储所有单词数据
        self.word_data = defaultdict(dict)
        
        # 记忆曲线间隔 (天)
        self.review_intervals = [1, 2, 4, 7, 15, 30, 60, 90]
    
    def add_word(self, word, meaning, example=""):
        """添加新单词"""
        today = datetime.date.today()
        if word not in self.word_data:
            self.word_data[word] = {
                'meaning': meaning,
                'example': example,
                'added_date': today,
                'last_reviewed': today,
                'next_review': today + datetime.timedelta(days=self.review_intervals[0]),
                'review_count': 0,
                'correct_count': 0,
                'incorrect_count': 0
            }

我们在这里使用列表来储存记忆曲线的节点,这样当我们核对各个单词的背诵时间时就可以与列表里的时间相比对,我们来详细分析这一句。

'next_review': today + datetime.timedelta(days=self.review_intervals[0])

它的意思是指当前日期加上预设的复习间隔天数。

today
代表当前日期,通常通过datetime.date.today()获取。需要确保代码中已正确定义该变量。

datetime.timedelta
Python标准库中用于表示时间间隔的类。days参数指定需要增加的天数。

self.review_intervals[0]
从对象属性中获取的第一个复习间隔天数。review_intervals应为预定义的列表或数组,存储着不同阶段的复习间隔

 2. 记忆算法实现

def review_word(self, word, is_correct):
    """记录单词复习结果并安排下次复习时间"""
    if word in self.word_data:
        info = self.word_data[word]
        info['last_reviewed'] = datetime.date.today()
        
        # 更新正确/错误计数
        if is_correct:
            info['correct_count'] += 1
        else:
            info['incorrect_count'] += 1
        
        # 根据记忆曲线安排下次复习时间
        review_count = min(info['review_count'], len(self.review_intervals) - 1)
        interval = self.review_intervals[review_count]
        
        # 如果不正确,缩短复习间隔
        if not is_correct:
            interval = max(1, interval // 2)
        
        info['next_review'] = datetime.date.today() + datetime.timedelta(days=interval)
        info['review_count'] += 1

这里我们需要做防越界处理:通过min()函数确保review_count不超过列表的最大索引。

3. 持久化存储

import json
import os

def load_data(self, data_file='word_memory_data.json'):
    """加载已有的单词数据"""
    self.data_file = data_file
    if os.path.exists(data_file):
        with open(data_file, 'r', encoding='utf-8') as f:
            data = json.load(f)
            # 将字符串日期转换为datetime.date对象
            for word, word_info in data.items():
                for key in ['added_date', 'last_reviewed', 'next_review']:
                    if key in word_info and word_info[key]:
                        word_info[key] = datetime.datetime.strptime(word_info[key], '%Y-%m-%d').date()
                self.word_data[word] = word_info

def save_data(self):
    """保存单词数据到文件"""
    # 将datetime.date对象转换为字符串
    data_to_save = {}
    for word, word_info in self.word_data.items():
        word_info_copy = word_info.copy()
        for key in ['added_date', 'last_reviewed', 'next_review']:
            if key in word_info_copy and word_info_copy[key]:
                word_info_copy[key] = word_info_copy[key].strftime('%Y-%m-%d')
        data_to_save[word] = word_info_copy
    
    with open(self.data_file, 'w', encoding='utf-8') as f:
        json.dump(data_to_save, f, ensure_ascii=False, indent=2)

 4. 用户界面实现

在这里,我们来编写用户在命令行里交互时所能看到的用户界面:

def learn_mode(self):
    """学习模式:逐个显示需要复习的单词"""
    words_to_review = self.get_words_to_review()
    
    if not words_to_review:
        print("恭喜!今天没有需要复习的单词。")
        return
    
    print(f"\n今天有 {len(words_to_review)} 个单词需要复习:")
    
    for word, info in words_to_review:
        print("\n" + "="*50)
        print(f"单词: {word}")
        input("按回车键查看意思...")
        print(f"意思: {info['meaning']}")
        if info['example']:
            print(f"例句: {info['example']}")
        
        while True:
            response = input("你记住了吗?(y/n): ").lower()
            if response in ['y', 'n']:
                self.review_word(word, response == 'y')
                break
            print("请输入 y 或 n")
    
    print("\n复习完成!")

5.整合与测试

接下来我们给程序添加main函数,就离大功告成不远了!

def main():
    system = WordMemorySystem()
    system.load_data()
    
    while True:
        print("\n" + "="*50)
        print("单词记忆系统")
        print("1. 添加新单词")
        print("2. 学习模式")
        print("3. 默写测试")
        print("4. 退出")
        
        choice = input("请选择操作: ")
        
        if choice == '1':
            word = input("输入单词: ").strip()
            meaning = input("输入意思: ").strip()
            example = input("输入例句 (可选): ").strip()
            system.add_word(word, meaning, example)
            system.save_data()
        
        elif choice == '2':
            system.learn_mode()
            system.save_data()
        
        elif choice == '3':
            system.test_mode()
            system.save_data()
        
        elif choice == '4':
            print("退出系统。")
            break
        
        else:
            print("无效选择,请重新输入。")

最后,我们来看看完整的代码:

import datetime
import json
import os
import random
from collections import defaultdict


class WordMemorySystem:
    def __init__(self, data_file='word_memory_data.json'):
        self.data_file = data_file
        self.word_data = defaultdict(dict)
        self.load_data()

        # 记忆曲线间隔 (天)
        self.review_intervals = [1, 2, 4, 7, 15, 30, 60, 90]

    def load_data(self):
        """加载已有的单词数据"""
        if os.path.exists(self.data_file):
            with open(self.data_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
                # 将字符串日期转换为datetime.date对象
                for word, word_info in data.items():
                    for key in ['added_date', 'last_reviewed', 'next_review']:
                        if key in word_info and word_info[key]:
                            word_info[key] = datetime.datetime.strptime(word_info[key], '%Y-%m-%d').date()
                    self.word_data[word] = word_info

    def save_data(self):
        """保存单词数据到文件"""
        # 将datetime.date对象转换为字符串
        data_to_save = {}
        for word, word_info in self.word_data.items():
            word_info_copy = word_info.copy()
            for key in ['added_date', 'last_reviewed', 'next_review']:
                if key in word_info_copy and word_info_copy[key]:
                    word_info_copy[key] = word_info_copy[key].strftime('%Y-%m-%d')
            data_to_save[word] = word_info_copy

        with open(self.data_file, 'w', encoding='utf-8') as f:
            json.dump(data_to_save, f, ensure_ascii=False, indent=2)

    def add_word(self, word, meaning, example=""):
        """添加新单词"""
        today = datetime.date.today()
        if word not in self.word_data:
            self.word_data[word] = {
                'meaning': meaning,
                'example': example,
                'added_date': today,
                'last_reviewed': today,
                'next_review': today + datetime.timedelta(days=self.review_intervals[0]),
                'review_count': 0,
                'correct_count': 0,
                'incorrect_count': 0
            }
            print(f"已添加单词: {word} - {meaning}")
        else:
            print(f"单词 '{word}' 已存在")
        self.save_data()

    def get_words_to_review(self):
        """获取今天需要复习的单词"""
        today = datetime.date.today()
        words_to_review = []

        for word, info in self.word_data.items():
            if 'next_review' in info and info['next_review'] <= today:
                words_to_review.append((word, info))

        # 按复习优先级排序 (先复习不熟悉的单词)
        words_to_review.sort(key=lambda x: (
            x[1]['incorrect_count'] / (x[1]['correct_count'] + x[1]['incorrect_count'] + 1),
            x[1]['next_review']
        ), reverse=True)

        return words_to_review

    def review_word(self, word, is_correct):
        """记录单词复习结果并安排下次复习时间"""
        if word in self.word_data:
            info = self.word_data[word]
            info['last_reviewed'] = datetime.date.today()

            # 更新正确/错误计数
            if is_correct:
                info['correct_count'] += 1
            else:
                info['incorrect_count'] += 1

            # 根据记忆曲线安排下次复习时间
            review_count = min(info['review_count'], len(self.review_intervals) - 1)
            interval = self.review_intervals[review_count]

            # 如果不正确,缩短复习间隔
            if not is_correct:
                interval = max(1, interval // 2)

            info['next_review'] = datetime.date.today() + datetime.timedelta(days=interval)
            info['review_count'] += 1

            self.save_data()

    def learn_mode(self):
        """学习模式:逐个显示需要复习的单词"""
        words_to_review = self.get_words_to_review()

        if not words_to_review:
            print("恭喜!今天没有需要复习的单词。")
            return

        print(f"\n今天有 {len(words_to_review)} 个单词需要复习:")

        for word, info in words_to_review:
            print("\n" + "=" * 50)
            print(f"单词: {word}")
            input("按回车键查看意思...")
            print(f"意思: {info['meaning']}")
            if info['example']:
                print(f"例句: {info['example']}")

            while True:
                response = input("你记住了吗?(y/n): ").lower()
                if response in ['y', 'n']:
                    self.review_word(word, response == 'y')
                    break
                print("请输入 y 或 n")

        print("\n复习完成!")

    def test_mode(self):
        """测试模式:默写测试"""
        words_to_review = self.get_words_to_review()

        if not words_to_review:
            print("今天没有需要复习的单词。")
            return

        print("\n默写测试模式 (输入 q 退出)")
        random.shuffle(words_to_review)

        for word, info in words_to_review:
            print("\n" + "=" * 50)
            print(f"意思: {info['meaning']}")
            if info['example']:
                print(f"例句: {info['example']}")

            user_input = input("请输入对应的单词: ").strip()

            if user_input.lower() == 'q':
                break

            if user_input.lower() == word.lower():
                print("正确!")
                self.review_word(word, True)
            else:
                print(f"错误!正确答案是: {word}")
                self.review_word(word, False)

        print("\n测试结束!")


def main():
    system = WordMemorySystem()

    while True:
        print("\n" + "=" * 50)
        print("单词记忆系统")
        print("1. 添加新单词")
        print("2. 学习模式")
        print("3. 默写测试")
        print("4. 查看所有单词")
        print("5. 查看今天需要复习的单词")
        print("6. 退出")

        choice = input("请选择操作: ")

        if choice == '1':
            word = input("输入单词: ").strip()
            meaning = input("输入意思: ").strip()
            example = input("输入例句 (可选): ").strip()
            system.add_word(word, meaning, example)

        elif choice == '2':
            system.learn_mode()

        elif choice == '3':
            system.test_mode()

        elif choice == '4':
            if not system.word_data:
                print("还没有添加任何单词。")
            else:
                print("\n所有单词:")
                for i, (word, info) in enumerate(system.word_data.items(), 1):
                    print(f"{i}. {word}: {info['meaning']}")
                    if info['example']:
                        print(f"   例句: {info['example']}")
                    print(
                        f"   添加日期: {info['added_date']}, 最后复习: {info['last_reviewed']}, 下次复习: {info['next_review']}")
                    print(f"   正确: {info['correct_count']}, 错误: {info['incorrect_count']}")

        elif choice == '5':
            words_to_review = system.get_words_to_review()
            if not words_to_review:
                print("今天没有需要复习的单词。")
            else:
                print(f"\n今天需要复习 {len(words_to_review)} 个单词:")
                for i, (word, info) in enumerate(words_to_review, 1):
                    print(f"{i}. {word}: {info['meaning']}")

        elif choice == '6':
            print("退出系统。")
            break

        else:
            print("无效选择,请重新输入。")


if __name__ == "__main__":
    main()

好的!那么今天的内容就到这里了,现在我们只能在命令行中操作它,之后也可以给它添加图形化界面使它更加有趣。
 


网站公告

今日签到

点亮在社区的每一天
去签到