今日目标完成一个完整的、可运行的待办事项清单程序实现任务的增、删、改、查、标记完成数据持久化保存重启程序数据不丢失学会项目功能拆解和模块化设计体验“给自己写工具”的成就感 一、项目需求分析我们来设计一个命令行版待办事项清单包含以下功能功能说明查看所有任务显示所有待办事项带编号和完成状态添加任务在清单末尾添加一个新的待办事项删除任务按编号删除指定的任务标记完成按编号将任务标记为已完成取消完成按编号将已完成的任务改回未完成反悔功能清空所有删除所有任务有二次确认统计信息显示总任务数、已完成数、未完成数数据持久化任务保存在todos.txt文件中重启程序自动加载 这个工具虽然简单但非常实用。很多人就是靠写这样的工具学会了编程。 二、数据结构设计2.1 数据存储格式我们用一个列表来存储所有任务每个任务是一个字典pythontodos [ {id: 1, text: 学习Python, done: False}, {id: 2, text: 写一篇博客, done: False}, {id: 3, text: 完成第14天练习, done: True}, ]2.2 文件存储格式保存到文件时我们用简单的文本格式每行一个任务text1|学习Python|False 2|写一篇博客|False 3|完成第14天练习|True用|分隔不同字段方便读取和解析。 这种简单的文本格式比JSON更直观新手也更容易理解。 三、代码结构设计texttodo.py ├── load_todos() # 从文件加载任务 ├── save_todos() # 保存任务到文件 ├── generate_id() # 生成新任务ID ├── show_todos() # 显示所有任务 ├── add_todo() # 添加任务 ├── delete_todo() # 删除任务 ├── complete_todo() # 标记完成 ├── uncomplete_todo() # 取消完成 ├── clear_all() # 清空所有 ├── show_stats() # 显示统计信息 ├── print_menu() # 打印菜单 └── main() # 主程序 四、逐步编写代码4.1 导入模块和定义常量pythonimport os TODO_FILE todos.txt4.2 加载任务从文件读取pythondef load_todos(): 从文件加载任务列表 返回: list: 任务列表每个任务是一个字典 todos [] if not os.path.exists(TODO_FILE): return todos try: with open(TODO_FILE, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue parts line.split(|) if len(parts) 3: todo { id: int(parts[0]), text: parts[1], done: parts[2] True } todos.append(todo) except Exception as e: print(f⚠️ 加载数据时出错: {e}) return todos4.3 保存任务写入文件pythondef save_todos(todos): 保存任务列表到文件 参数: todos: 任务列表 try: with open(TODO_FILE, w, encodingutf-8) as f: for todo in todos: f.write(f{todo[id]}|{todo[text]}|{todo[done]}\n) return True except Exception as e: print(f❌ 保存数据时出错: {e}) return False4.4 生成新IDpythondef generate_id(todos): 生成新的任务ID当前最大ID 1 参数: todos: 任务列表 返回: int: 新ID if not todos: return 1 return max(todo[id] for todo in todos) 14.5 显示所有任务pythondef show_todos(todos): 显示所有任务 参数: todos: 任务列表 if not todos: print(\n 暂无待办事项添加一些吧) return print(\n * 50) print( 待办清单) print( * 50) # 按状态分组显示 undone [t for t in todos if not t[done]] done [t for t in todos if t[done]] # 显示未完成的 if undone: print(\n⏳ 待完成:) for todo in undone: print(f [{todo[id]:2d}] {todo[text]}) # 显示已完成的 if done: print(\n✅ 已完成:) for todo in done: print(f [{todo[id]:2d}] {todo[text]} {chr(10003)}) # ✓ 符号 print(\n - * 50) print(f总计: {len(todos)} 项 | 待完成: {len(undone)} 项 | 已完成: {len(done)} 项) print( * 50)4.6 添加任务pythondef add_todo(todos): 添加新任务 参数: todos: 任务列表 返回: bool: 是否成功 text input(\n请输入新的待办事项: ).strip() if not text: print(❌ 任务内容不能为空) return False todo { id: generate_id(todos), text: text, done: False } todos.append(todo) save_todos(todos) print(f✅ 已添加: {text}) return True4.7 删除任务pythondef delete_todo(todos): 删除指定编号的任务 参数: todos: 任务列表 if not todos: print(\n 没有任务可删除) return show_todos(todos) try: todo_id int(input(\n请输入要删除的任务编号: )) # 查找任务 for i, todo in enumerate(todos): if todo[id] todo_id: confirm input(f确认删除 {todo[text]}(y/n): ).lower() if confirm y or confirm yes: removed todos.pop(i) save_todos(todos) print(f✅ 已删除: {removed[text]}) else: print(已取消删除) return print(f❌ 未找到编号为 {todo_id} 的任务) except ValueError: print(❌ 请输入有效的数字编号)4.8 标记完成pythondef complete_todo(todos): 标记任务为已完成 参数: todos: 任务列表 undone [t for t in todos if not t[done]] if not undone: print(\n 所有任务都已完成) return show_todos(todos) try: todo_id int(input(\n请输入要标记完成的任务编号: )) for todo in todos: if todo[id] todo_id: if todo[done]: print(f⚠️ {todo[text]} 已经完成了) return todo[done] True save_todos(todos) print(f✅ 已标记完成: {todo[text]}) return print(f❌ 未找到编号为 {todo_id} 的任务) except ValueError: print(❌ 请输入有效的数字编号)4.9 取消完成反悔功能pythondef uncomplete_todo(todos): 将已完成的任务改回未完成 参数: todos: 任务列表 done [t for t in todos if t[done]] if not done: print(\n 没有已完成的任务) return show_todos(todos) try: todo_id int(input(\n请输入要取消完成的任务编号: )) for todo in todos: if todo[id] todo_id: if not todo[done]: print(f⚠️ {todo[text]} 本来就是未完成状态) return todo[done] False save_todos(todos) print(f✅ 已取消完成: {todo[text]}) return print(f❌ 未找到编号为 {todo_id} 的任务) except ValueError: print(❌ 请输入有效的数字编号)4.10 清空所有任务pythondef clear_all(todos): 清空所有任务二次确认 参数: todos: 任务列表 if not todos: print(\n 已经是空清单了) return show_todos(todos) confirm input(\n⚠️ 确认删除所有任务(y/n): ).lower() if confirm y or confirm yes: todos.clear() save_todos(todos) print(️ 已清空所有任务) else: print(已取消操作)4.11 显示统计信息pythondef show_stats(todos): 显示统计信息 参数: todos: 任务列表 if not todos: print(\n 暂无任务) return total len(todos) done_count sum(1 for t in todos if t[done]) undone_count total - done_count completion_rate (done_count / total * 100) if total 0 else 0 print(\n * 40) print( 统计信息) print( * 40) print(f总任务数: {total}) print(f已完成: {done_count} 项) print(f待完成: {undone_count} 项) print(f完成率: {completion_rate:.1f}%) # 显示进度条 bar_length 20 filled int(bar_length * completion_rate / 100) bar █ * filled ░ * (bar_length - filled) print(f进度条: [{bar}]) print( * 40)4.12 打印菜单pythondef print_menu(): 打印主菜单 print(\n * 40) print( 待办事项清单) print( * 40) print(1. 查看所有任务) print(2. 添加新任务) print(3. 删除任务) print(4. 标记完成) print(5. 取消完成反悔) print(6. 清空所有任务) print(7. 统计信息) print(8. 退出) print( * 40)4.13 主程序pythondef main(): 主程序 # 加载任务 todos load_todos() print( * 40) print( 待办事项清单) print( * 40) print(f已加载 {len(todos)} 项任务) # 主循环 while True: print_menu() choice input(请选择操作1-8: ) if choice 1: show_todos(todos) elif choice 2: add_todo(todos) elif choice 3: delete_todo(todos) elif choice 4: complete_todo(todos) elif choice 5: uncomplete_todo(todos) elif choice 6: clear_all(todos) elif choice 7: show_stats(todos) elif choice 8: # 保存数据 save_todos(todos) print(\n 再见数据已保存。) break else: print(❌ 无效选择请输入 1-8) if __name__ __main__: main() 五、完整代码以下是完整的todo.py文件python 第14天实战项目待办事项清单命令行版 综合运用列表、字典、函数、文件操作、异常处理、模块化设计 import os TODO_FILE todos.txt def load_todos(): 从文件加载任务列表 返回: list: 任务列表每个任务是一个字典 todos [] if not os.path.exists(TODO_FILE): return todos try: with open(TODO_FILE, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue parts line.split(|) if len(parts) 3: todo { id: int(parts[0]), text: parts[1], done: parts[2] True } todos.append(todo) except Exception as e: print(f⚠️ 加载数据时出错: {e}) return todos def save_todos(todos): 保存任务列表到文件 参数: todos: 任务列表 try: with open(TODO_FILE, w, encodingutf-8) as f: for todo in todos: f.write(f{todo[id]}|{todo[text]}|{todo[done]}\n) return True except Exception as e: print(f❌ 保存数据时出错: {e}) return False def generate_id(todos): 生成新的任务ID当前最大ID 1 参数: todos: 任务列表 返回: int: 新ID if not todos: return 1 return max(todo[id] for todo in todos) 1 def show_todos(todos): 显示所有任务 参数: todos: 任务列表 if not todos: print(\n 暂无待办事项添加一些吧) return print(\n * 50) print( 待办清单) print( * 50) undone [t for t in todos if not t[done]] done [t for t in todos if t[done]] if undone: print(\n⏳ 待完成:) for todo in undone: print(f [{todo[id]:2d}] {todo[text]}) if done: print(\n✅ 已完成:) for todo in done: print(f [{todo[id]:2d}] {todo[text]} ✓) print(\n - * 50) print(f总计: {len(todos)} 项 | 待完成: {len(undone)} 项 | 已完成: {len(done)} 项) print( * 50) def add_todo(todos): 添加新任务 参数: todos: 任务列表 返回: bool: 是否成功 text input(\n请输入新的待办事项: ).strip() if not text: print(❌ 任务内容不能为空) return False todo { id: generate_id(todos), text: text, done: False } todos.append(todo) save_todos(todos) print(f✅ 已添加: {text}) return True def delete_todo(todos): 删除指定编号的任务 参数: todos: 任务列表 if not todos: print(\n 没有任务可删除) return show_todos(todos) try: todo_id int(input(\n请输入要删除的任务编号: )) for i, todo in enumerate(todos): if todo[id] todo_id: confirm input(f确认删除 {todo[text]}(y/n): ).lower() if confirm y or confirm yes: removed todos.pop(i) save_todos(todos) print(f✅ 已删除: {removed[text]}) else: print(已取消删除) return print(f❌ 未找到编号为 {todo_id} 的任务) except ValueError: print(❌ 请输入有效的数字编号) def complete_todo(todos): 标记任务为已完成 参数: todos: 任务列表 undone [t for t in todos if not t[done]] if not undone: print(\n 所有任务都已完成) return show_todos(todos) try: todo_id int(input(\n请输入要标记完成的任务编号: )) for todo in todos: if todo[id] todo_id: if todo[done]: print(f⚠️ {todo[text]} 已经完成了) return todo[done] True save_todos(todos) print(f✅ 已标记完成: {todo[text]}) return print(f❌ 未找到编号为 {todo_id} 的任务) except ValueError: print(❌ 请输入有效的数字编号) def uncomplete_todo(todos): 将已完成的任务改回未完成 参数: todos: 任务列表 done [t for t in todos if t[done]] if not done: print(\n 没有已完成的任务) return show_todos(todos) try: todo_id int(input(\n请输入要取消完成的任务编号: )) for todo in todos: if todo[id] todo_id: if not todo[done]: print(f⚠️ {todo[text]} 本来就是未完成状态) return todo[done] False save_todos(todos) print(f✅ 已取消完成: {todo[text]}) return print(f❌ 未找到编号为 {todo_id} 的任务) except ValueError: print(❌ 请输入有效的数字编号) def clear_all(todos): 清空所有任务二次确认 参数: todos: 任务列表 if not todos: print(\n 已经是空清单了) return show_todos(todos) confirm input(\n⚠️ 确认删除所有任务(y/n): ).lower() if confirm y or confirm yes: todos.clear() save_todos(todos) print(️ 已清空所有任务) else: print(已取消操作) def show_stats(todos): 显示统计信息 参数: todos: 任务列表 if not todos: print(\n 暂无任务) return total len(todos) done_count sum(1 for t in todos if t[done]) undone_count total - done_count completion_rate (done_count / total * 100) if total 0 else 0 print(\n * 40) print( 统计信息) print( * 40) print(f总任务数: {total}) print(f已完成: {done_count} 项) print(f待完成: {undone_count} 项) print(f完成率: {completion_rate:.1f}%) bar_length 20 filled int(bar_length * completion_rate / 100) bar █ * filled ░ * (bar_length - filled) print(f进度条: [{bar}]) print( * 40) def print_menu(): 打印主菜单 print(\n * 40) print( 待办事项清单) print( * 40) print(1. 查看所有任务) print(2. 添加新任务) print(3. 删除任务) print(4. 标记完成) print(5. 取消完成反悔) print(6. 清空所有任务) print(7. 统计信息) print(8. 退出) print( * 40) def main(): 主程序 todos load_todos() print( * 40) print( 待办事项清单) print( * 40) print(f已加载 {len(todos)} 项任务) while True: print_menu() choice input(请选择操作1-8: ) if choice 1: show_todos(todos) elif choice 2: add_todo(todos) elif choice 3: delete_todo(todos) elif choice 4: complete_todo(todos) elif choice 5: uncomplete_todo(todos) elif choice 6: clear_all(todos) elif choice 7: show_stats(todos) elif choice 8: save_todos(todos) print(\n 再见数据已保存。) break else: print(❌ 无效选择请输入 1-8) if __name__ __main__: main() 六、运行结果演示启动程序text 待办事项清单 已加载 3 项任务 待办事项清单 1. 查看所有任务 2. 添加新任务 3. 删除任务 4. 标记完成 5. 取消完成反悔 6. 清空所有任务 7. 统计信息 8. 退出 请选择操作1-8: 1 待办清单 ⏳ 待完成: [ 1] 学习Python [ 2] 写一篇博客 ✅ 已完成: [ 3] 完成第14天练习 ✓ -------------------------------------------------- 总计: 3 项 | 待完成: 2 项 | 已完成: 1 项 添加任务text请选择操作1-8: 2 请输入新的待办事项: 去超市买菜 ✅ 已添加: 去超市买菜标记完成text请选择操作1-8: 4 待办清单 ⏳ 待完成: [ 1] 学习Python [ 2] 写一篇博客 [ 4] 去超市买菜 ✅ 已完成: [ 3] 完成第14天练习 ✓ -------------------------------------------------- 总计: 4 项 | 待完成: 3 项 | 已完成: 1 项 请输入要标记完成的任务编号: 4 ✅ 已标记完成: 去超市买菜统计信息text请选择操作1-8: 7 统计信息 总任务数: 4 已完成: 2 项 待完成: 2 项 完成率: 50.0% 进度条: [██████████░░░░░░░░░░] 今日总结今天你通过待办事项清单项目综合运用了知识点用在什么地方列表存储所有任务字典每个任务的“ID、内容、状态”函数每个功能独立封装文件操作读取和保存todos.txt异常处理输入校验、文件读写错误循环主菜单循环条件判断菜单路由、状态判断列表推导式筛选已完成/未完成的任务模块化设计一个函数做一件事