Python 入门实战:从零写一个命令行待办清单工具
很多新手学完 Python 语法,却不知道第一个能真正用起来的程序该写什么。待办清单是一个很好的起点:它足够小,可以在一个文件里完成;又足够真实,涉及输入、存储、查询和修改,几乎覆盖了日常编程最常用的思路。本文就用标准库完成一个命令行待办清单,不依赖第三方包,也不需要数据库。
先想清楚:程序要解决什么问题
在写代码之前,先把需求写成一句话:用户可以在命令行添加任务、查看任务、标记完成和删除任务,关闭程序后数据仍然存在。这句话里已经藏着三个设计要点。第一,任务需要一个唯一标识,否则删除和完成时容易改错行。第二,任务至少要有内容和完成状态两个字段。第三,数据要落盘保存,否则每次启动都会丢失。
用字典和列表表示任务
最直观的做法,是用一个字典表示一条任务,用列表保存全部任务。例如每条任务包含编号、内容和是否完成。编号可以按已有任务的最大值加一生成,避免重复。列表的好处是顺序自然,打印时也方便编号。初学者常常一开始就想设计很复杂的类,其实先把数据结构想简单,程序反而更容易写对。
用 JSON 文件做持久化
保存数据不需要先学数据库,Python 标准库里的 json 模块就够了。程序启动时先读取一个 JSON 文件,如果文件不存在,就从空列表开始;退出或每次修改后,再把列表写回文件。这样做还有一个好处:数据文件是纯文本,出了问题可以直接打开查看。需要注意的是,写入时要处理好中文编码,读取时要对文件损坏的情况做基本容错,不要让一次异常就把全部数据弄丢。
命令行入口要简单直观
命令可以设计得很直接:add 后面跟任务内容,list 查看全部任务,done 后面跟编号表示完成,delete 后面跟编号表示删除。实现时可以用 sys.argv 读取参数,也可以用 argparse 生成更友好的帮助信息。对新手来说,先用 sys.argv 理解参数就是字符串列表,再过渡到 argparse 会更自然。每个命令对应一个小函数,主函数只负责分发,这样以后加新命令时改动也很小。
演示与自测
写完后可以按顺序做一次完整演练:添加三条任务,查看列表,标记其中一条完成,再删除一条,最后重新启动程序确认剩余任务还在。如果某一步结果不对,先打印任务列表和文件内容,确认是命令解析错了,还是数据保存错了。把问题定位到一层,比反复改代码更有效。
新手最容易踩的三个坑
第一是编号和列表下标混淆。用户看到的编号从一开始,而列表下标从零开始,转换时要小心。第二是忘记保存。只改了内存里的列表,没有写回文件,下次启动就会以为程序丢了数据。第三是把所有逻辑都写进一个大函数里,导致调试困难。按添加、查看、完成、删除和保存拆成小函数,是很好的练习。
可以继续扩展的方向
完成基础版后,可以再加三个小功能:按完成状态筛选、给任务加截止日期、支持简单的关键词搜索。这些扩展都不需要换技术栈,却能让你练习条件判断、日期处理和字符串匹配。等你对这个小工具足够熟悉,再去学习面向对象、单元测试或图形界面,都会有更具体的落脚点。
import json
import sys
FILE = "todos.json"
def load():
try:
with open(FILE, encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return []
def save(todos):
with open(FILE, "w", encoding="utf-8") as f:
json.dump(todos, f, ensure_ascii=False, indent=2)
def main():
todos = load()
if len(sys.argv) < 2:
print("用法:python todo.py add/list/done/delete")
return
cmd = sys.argv[1]
if cmd == "add" and len(sys.argv) > 2:
new_id = max([t["id"] for t in todos], default=0) + 1
todos.append({"id": new_id, "text": sys.argv[2], "done": False})
save(todos)
elif cmd == "list":
for t in todos:
mark = "完成" if t["done"] else "待办"
print(t["id"], mark, t["text"])
总结一下:先想清楚数据,再写读写逻辑,最后把命令拆成小函数。一个能每天用起来的小工具,比十个只跑过一次的示例更有价值。
- 点赞
- 收藏
- 关注作者
评论(0)