目标

写一个命令行 todo 工具,支持:

$ python todo.py add "买菜"
✓ 已添加 #1 买菜

$ python todo.py list
[ ] #1 买菜

$ python todo.py done 1
✓ 完成 #1

$ python todo.py list
[x] #1 买菜

数据存到本地 todos.json 文件。

完整代码

# todo.py
import json
import sys
from pathlib import Path

DATA_FILE = Path("todos.json")


class TodoStore:
    def __init__(self, file: Path):
        self.file = file
        self.todos = self._load()

    def _load(self):
        if not self.file.exists():
            return []
        try:
            return json.loads(self.file.read_text(encoding="utf-8"))
        except json.JSONDecodeError:
            print("⚠ 数据文件损坏,重置")
            return []

    def _save(self):
        self.file.write_text(
            json.dumps(self.todos, ensure_ascii=False, indent=2),
            encoding="utf-8",
        )

    def add(self, text):
        next_id = (max((t["id"] for t in self.todos), default=0)) + 1
        self.todos.append({"id": next_id, "text": text, "done": False})
        self._save()
        print(f"✓ 已添加 #{next_id} {text}")

    def list(self):
        if not self.todos:
            print("(暂无 todo)")
            return
        for t in self.todos:
            mark = "x" if t["done"] else " "
            print(f"[{mark}] #{t['id']} {t['text']}")

    def done(self, tid):
        for t in self.todos:
            if t["id"] == tid:
                t["done"] = True
                self._save()
                print(f"✓ 完成 #{tid}")
                return
        print(f"⚠ 找不到 #{tid}")


def main():
    store = TodoStore(DATA_FILE)
    args = sys.argv[1:]

    if not args:
        print("用法: python todo.py [add|list|done] ...")
        return

    cmd = args[0]

    if cmd == "add" and len(args) >= 2:
        store.add(" ".join(args[1:]))
    elif cmd == "list":
        store.list()
    elif cmd == "done" and len(args) >= 2:
        try:
            store.done(int(args[1]))
        except ValueError:
            print("⚠ ID 必须是数字")
    else:
        print(f"⚠ 未知命令: {cmd}")


if __name__ == "__main__":
    main()

用了哪些前面学过的东西

知识点 出现位置
类 + __init__ + self TodoStore
默认参数 default=0
列表 / 字典 self.todos
文件读写 _load / _save
异常处理 json.JSONDecodeError
f-string print 输出
模块 import json / sys / pathlib
pathlib DATA_FILE
命令行参数 sys.argv
推导式 max(... default=0)
if __name__ == "__main__" 入口

试着扩展

  • delete <id> 命令
  • --priority 标记
  • 加 deadline 日期,list 时按 deadline 排序
  • 改用 argparse 做更专业的命令行解析

写完这些,你的 Python 基础就过关了。

下一篇:基础课程总结 + 路线图。