最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Python編寫一個待辦事項管理器(CLI?版)

 更新時間:2026年04月28日 09:34:59   作者:SilentSamsara  
這篇文章主要為大家詳細(xì)介紹了如何使用Python編寫一個命令行待辦事項管理器,可以把列表、字典、函數(shù)、文件操作、異常處理、標(biāo)準(zhǔn)庫全部串聯(lián)起來,成為一個可以每天使用的工具,感興趣的小伙伴可以了解下

本篇的目標(biāo)是做一個真正能跑的命令行待辦事項管理器。把列表、字典、函數(shù)、文件操作、異常處理、標(biāo)準(zhǔn)庫全部串聯(lián)起來,成為一個可以每天使用的工具。

知識點(diǎn)串聯(lián)表

功能涉及的前置知識點(diǎn)
待辦項存儲(dict + 列表)#04 列表與字典
每個功能一個函數(shù)#05 函數(shù)入門
主循環(huán) + 輸入驗(yàn)證#03 條件判斷與循環(huán)
文件不存在時自動創(chuàng)建#06 文件操作 + #07 錯誤與異常
JSON 數(shù)據(jù)持久化#06 json 模塊
菜單選項 → 函數(shù)映射#03 + #04 字典做映射
加載標(biāo)準(zhǔn)庫工具#09 模塊與包
類封裝(可選進(jìn)階)#08 類與對象

一、先看架構(gòu)

在寫代碼之前,先把程序的結(jié)構(gòu)想清楚。整體是一個菜單驅(qū)動的循環(huán)程序

數(shù)據(jù)存儲結(jié)構(gòu)是這樣的:

// todos.json
[
  {
    "id": 1,
    "title": "閱讀模塊與包文章",
    "completed": false,
    "created_at": "2026-04-27 09:15"
  },
  {
    "id": 2,
    "title": "整理 Python 筆記",
    "completed": true,
    "created_at": "2026-04-26 20:30"
  }
]

二、第一步:內(nèi)存版——只管添加和查看

先寫一個最簡單版本,不涉及文件操作。所有待辦項存在內(nèi)存列表里,程序退出就消失——這個版本用來驗(yàn)證數(shù)據(jù)結(jié)構(gòu)是否合理。

2.1 定義數(shù)據(jù)結(jié)構(gòu)

每個待辦項是一個字典,包含:

  • id:唯一編號,用于精確定位每條記錄
  • title:待辦內(nèi)容
  • completed:是否已完成(布爾值)
  • created_at:創(chuàng)建時間
import datetime

todos = []          # 全局列表,存儲所有待辦項
next_id = 1        # 下一個可用的 ID


def add_todo(title):
    global next_id
    todo = {
        "id": next_id,
        "title": title,
        "completed": False,
        "created_at": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
    }
    todos.append(todo)
    next_id += 1
    print(f"? 已添加:{title}")


def list_todos():
    if not todos:
        print("?? 暫無待辦事項")
        return

    for todo in todos:
        status = "?" if todo["completed"] else "○"
        print(f"  [{status}] #{todo['id']} {todo['title']}")

2.2 測試這兩個函數(shù)

add_todo("閱讀模塊與包文章")
add_todo("整理 Python 筆記")
add_todo("完成待辦管理器 v1")
list_todos()

輸出:

? 已添加:閱讀模塊與包文章
? 已添加:整理 Python 筆記
? 已添加:完成待辦管理器 v1
  [○] #1 閱讀模塊與包文章
  [○] #2 整理 Python 筆記
  [○] #3 完成待辦管理器 v1

關(guān)鍵理解:到這里,待辦項的數(shù)據(jù)結(jié)構(gòu)已經(jīng)驗(yàn)證完畢。后續(xù)所有工作都是在這些基礎(chǔ)上加功能,而不是重新設(shè)計數(shù)據(jù)結(jié)構(gòu)。

三、第二步:加上標(biāo)記完成和刪除

3.1 標(biāo)記完成

用戶輸入待辦 ID,程序找到對應(yīng)項并將其 completed 設(shè)為 True

def complete_todo(todo_id):
    for todo in todos:
        if todo["id"] == todo_id:
            if todo["completed"]:
                print(f"??  #{todo_id} 已經(jīng)是完成狀態(tài)")
                return
            todo["completed"] = True
            print(f"?? #{todo_id} {todo['title']} 已標(biāo)記完成")
            return
    print(f"? 未找到 ID 為 {todo_id} 的待辦項")

3.2 刪除待辦

def delete_todo(todo_id):
    for i, todo in enumerate(todos):
        if todo["id"] == todo_id:
            removed = todos.pop(i)
            print(f"???  已刪除:{removed['title']}")
            return
    print(f"? 未找到 ID 為 {todo_id} 的待辦項")

注意pop(i) 按索引刪除——但查找時用的是 id(內(nèi)容),刪除時用的是 enumerate 獲取的索引 i。這兩個操作必須配合,不能直接用 id 作為列表索引,因?yàn)?ID 是邏輯編號,不等于列表下標(biāo)。

測試:

complete_todo(2)
delete_todo(3)
list_todos()

輸出:

?? #2 整理 Python 筆記 已標(biāo)記完成
???  已刪除:完成待辦管理器 v1
  [○] #1 閱讀模塊與包文章
  [?] #2 整理 Python 筆記

四、第三步:加上 JSON 文件持久化

內(nèi)存版本的致命問題是程序退出后數(shù)據(jù)全丟了。加一層文件操作,讓數(shù)據(jù)保存到 todos.json。

4.1 保存和加載函數(shù)

import json
import os

FILENAME = "todos.json"


def save_todos():
    """將當(dāng)前 todos 列表寫入 JSON 文件"""
    with open(FILENAME, "w", encoding="utf-8") as f:
        json.dump(todos, f, ensure_ascii=False, indent=2)
    print(f"?? 已保存到 {FILENAME}")


def load_todos():
    """從 JSON 文件加載待辦項列表"""
    global next_id
    if not os.path.exists(FILENAME):
        print("?? 首次運(yùn)行,創(chuàng)建空數(shù)據(jù)文件")
        return

    with open(FILENAME, "r", encoding="utf-8") as f:
        loaded = json.load(f)

    todos.clear()
    todos.extend(loaded)

    # 恢復(fù) next_id:已有 ID 的最大值 + 1
    if todos:
        next_id = max(t["id"] for t in todos) + 1
    else:
        next_id = 1

    print(f"?? 已從 {FILENAME} 加載 {len(todos)} 條待辦")


def add_todo(title):
    global next_id
    todo = {
        "id": next_id,
        "title": title,
        "completed": False,
        "created_at": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
    }
    todos.append(todo)
    next_id += 1
    save_todos()           # 每次添加后自動保存
    print(f"? 已添加:{title}")


def complete_todo(todo_id):
    for todo in todos:
        if todo["id"] == todo_id:
            todo["completed"] = True
            save_todos()
            print(f"?? #{todo_id} {todo['title']} 已標(biāo)記完成")
            return
    print(f"? 未找到 ID 為 {todo_id} 的待辦項")


def delete_todo(todo_id):
    for i, todo in enumerate(todos):
        if todo["id"] == todo_id:
            removed = todos.pop(i)
            save_todos()
            print(f"???  已刪除:{removed['title']}")
            return
    print(f"? 未找到 ID 為 {todo_id} 的待辦項")

設(shè)計說明:把 save_todos() 嵌入了 add_todo、complete_todo、delete_todo 三個函數(shù)——這叫"每次修改后立即保存",簡單可靠。復(fù)雜系統(tǒng)會用事務(wù)或緩沖,但這里每條操作都足夠輕量,即時保存沒有性能問題。

五、第四步:加上主循環(huán)和異常處理

5.1 菜單選項 → 函數(shù)映射

用字典替代大量 if/elif,是讓代碼更優(yōu)雅的實(shí)用技巧:

MENU = """
========================================
         ?? 待辦事項管理器
========================================
  1. 添加待辦
  2. 查看待辦
  3. 標(biāo)記完成
  4. 刪除待辦
  5. 退出
========================================
請輸入選項(1-5):
"""

主循環(huán):

def main():
    load_todos()

    while True:
        try:
            choice = input(MENU).strip()

            if choice == "1":
                title = input("請輸入待辦內(nèi)容:").strip()
                if not title:
                    print("??  內(nèi)容不能為空")
                    continue
                add_todo(title)

            elif choice == "2":
                list_todos()

            elif choice == "3":
                list_todos()
                if not todos:
                    continue
                try:
                    todo_id = int(input("請輸入要完成的待辦 ID:").strip())
                except ValueError:
                    print("??  請輸入數(shù)字 ID")
                    continue
                complete_todo(todo_id)

            elif choice == "4":
                list_todos()
                if not todos:
                    continue
                try:
                    todo_id = int(input("請輸入要刪除的待辦 ID:").strip())
                except ValueError:
                    print("??  請輸入數(shù)字 ID")
                    continue
                delete_todo(todo_id)

            elif choice == "5":
                print("?? 下次見!")
                break

            else:
                print("??  無效選項,請輸入 1-5 之間的數(shù)字")

        except KeyboardInterrupt:
            print("\n?? 強(qiáng)制退出,下次見!")
            break


if __name__ == "__main__":
    main()

5.2 異常處理的三處場景

這段代碼里有三處不同類型的異常處理,各自解決不同問題:

位置異常類型保護(hù)什么
int(input(...))ValueError用戶輸入了非數(shù)字內(nèi)容
open(FILENAME, "r")FileNotFoundError數(shù)據(jù)文件不存在(load_todos 里已處理)
input() 外層KeyboardInterrupt用戶按 Ctrl+C 強(qiáng)制退出

六、完整代碼

把所有部分組合在一起,加上注釋和 docstring:

"""
待辦事項管理器 v1.0
命令行界面,數(shù)據(jù)持久化到 JSON 文件
"""

import json
import os
import datetime

FILENAME = "todos.json"
todos = []
next_id = 1


def load_todos():
    """從 JSON 文件加載待辦項列表,不存在則創(chuàng)建空文件"""
    global next_id
    if not os.path.exists(FILENAME):
        open(FILENAME, "w", encoding="utf-8").close()
        print("?? 首次運(yùn)行,已創(chuàng)建空數(shù)據(jù)文件")
        return

    try:
        with open(FILENAME, "r", encoding="utf-8") as f:
            data = json.load(f)
        todos.clear()
        todos.extend(data)
        next_id = (max(t["id"] for t in todos) + 1) if todos else 1
        print(f"?? 已加載 {len(todos)} 條待辦")
    except (json.JSONDecodeError, IOError) as e:
        print(f"??  數(shù)據(jù)文件讀取失敗,將使用空列表:{e}")


def save_todos():
    """將當(dāng)前 todos 列表寫入 JSON 文件"""
    try:
        with open(FILENAME, "w", encoding="utf-8") as f:
            json.dump(todos, f, ensure_ascii=False, indent=2)
    except IOError as e:
        print(f"? 保存失?。簕e}")


def add_todo(title):
    """添加一條待辦項"""
    global next_id
    todo = {
        "id": next_id,
        "title": title,
        "completed": False,
        "created_at": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
    }
    todos.append(todo)
    next_id += 1
    save_todos()
    print(f"? 已添加 [{todo['id']}] {title}")


def list_todos(filter_status=None):
    """列出所有待辦項,支持按狀態(tài)過濾"""
    if not todos:
        print("?? 暫無待辦事項")
        return

    print("\n" + "=" * 40)
    for todo in todos:
        if filter_status is not None and todo["completed"] != filter_status:
            continue
        status = "?" if todo["completed"] else "○"
        line = f"  [{status}] #{todo['id']} {todo['title']}"
        if todo["completed"]:
            line += f" ({todo['created_at']})"
        print(line)
    print("=" * 40)
    print(f"共 {len(todos)} 條,"
          f"已完成 {sum(1 for t in todos if t['completed'])} 條,"
          f"未完成 {sum(1 for t in todos if not t['completed'])} 條")


def complete_todo(todo_id):
    """將指定 ID 的待辦標(biāo)記為已完成"""
    for todo in todos:
        if todo["id"] == todo_id:
            if todo["completed"]:
                print(f"??  #{todo_id} 已經(jīng)是完成狀態(tài)")
                return
            todo["completed"] = True
            save_todos()
            print(f"?? #{todo_id} 已標(biāo)記完成:{todo['title']}")
            return
    print(f"? 未找到 ID 為 {todo_id} 的待辦項")


def delete_todo(todo_id):
    """刪除指定 ID 的待辦項"""
    for i, todo in enumerate(todos):
        if todo["id"] == todo_id:
            removed = todos.pop(i)
            save_todos()
            print(f"???  已刪除:{removed['title']}")
            return
    print(f"? 未找到 ID 為 {todo_id} 的待辦項")


def main():
    load_todos()

    MENU = """
========================================
         ?? 待辦事項管理器 v1.0
========================================
  1. 添加待辦
  2. 查看全部
  3. 查看未完成
  4. 查看已完成
  5. 標(biāo)記完成
  6. 刪除待辦
  7. 退出
========================================
    """

    while True:
        try:
            choice = input(MENU).strip()

            if choice == "1":
                title = input("請輸入待辦內(nèi)容:").strip()
                if not title:
                    print("??  內(nèi)容不能為空")
                    continue
                add_todo(title)

            elif choice == "2":
                list_todos()

            elif choice == "3":
                list_todos(filter_status=False)

            elif choice == "4":
                list_todos(filter_status=True)

            elif choice == "5":
                list_todos(filter_status=False)
                if not todos:
                    continue
                raw = input("請輸入要完成的待辦 ID(直接回車取消):").strip()
                if not raw:
                    continue
                try:
                    complete_todo(int(raw))
                except ValueError:
                    print("??  請輸入數(shù)字")

            elif choice == "6":
                list_todos()
                if not todos:
                    continue
                raw = input("請輸入要刪除的待辦 ID(直接回車取消):").strip()
                if not raw:
                    continue
                try:
                    delete_todo(int(raw))
                except ValueError:
                    print("??  請輸入數(shù)字")

            elif choice == "7":
                print("?? 下次見!")
                break

            else:
                print("??  無效選項,請輸入 1-7")

        except KeyboardInterrupt:
            print("\n?? 下次見!")
            break


if __name__ == "__main__":
    main()

七、運(yùn)行效果

$ python todo_manager.py
?? 已加載 3 條待辦

========================================
         ?? 待辦事項管理器 v1.0
========================================
  1. 添加待辦
  2. 查看全部
  3. 查看未完成
  4. 查看已完成
  5. 標(biāo)記完成
  6. 刪除待辦
  7. 退出
========================================

請輸入選項(1-7):
2

========================================
  [○] #1 閱讀模塊與包文章
  [?] #2 整理 Python 筆記
  [○] #3 完成待辦管理器 v1
========================================
共 3 條,已完成 1 條,未完成 2 條

請輸入選項(1-7):
1
請輸入待辦內(nèi)容:發(fā)布文章到 CSDN
?? 已保存到 todos.json
? 已添加 [4] 發(fā)布文章到 CSDN

請輸入選項(1-7):
5

========================================
  [○] #1 閱讀模塊與包文章
  [○] #3 完成待辦管理器 v1
  [○] #4 發(fā)布文章到 CSDN
========================================
共 3 條,已完成 0 條,未完成 3 條

請輸入要完成的待辦 ID(直接回車取消):3
?? 已保存到 todos.json
?? #3 已標(biāo)記完成:完成待辦管理器 v1

請輸入選項(1-7):
7
?? 下次見!

程序退出后,todos.json 文件里已經(jīng)保存了所有數(shù)據(jù),下次運(yùn)行會自動加載:

[
  {
    "id": 1,
    "title": "閱讀模塊與包文章",
    "completed": false,
    "created_at": "2026-04-27 09:15"
  },
  {
    "id": 2,
    "title": "整理 Python 筆記",
    "completed": true,
    "created_at": "2026-04-26 20:30"
  },
  {
    "id": 3,
    "title": "完成待辦管理器 v1",
    "completed": true,
    "created_at": "2026-04-27 10:00"
  },
  {
    "id": 4,
    "title": "發(fā)布文章到 CSDN",
    "completed": false,
    "created_at": "2026-04-27 10:05"
  }
]

八、擴(kuò)展方向:讓工具更接近真實(shí)產(chǎn)品

當(dāng)前版本可以正常工作,但真實(shí)場景中還需要更多功能。以下是幾個典型的擴(kuò)展方向,每個都能獨(dú)立成一個小專題:

擴(kuò)展功能涉及的新知識點(diǎn)
優(yōu)先級(高/中/低)字典增加 priority 字段,列表排序 sort(key=...)
截止日期 + 排序datetime 模塊,按日期排序
分類標(biāo)簽列表的列表或 set,支持多標(biāo)簽
命令行參數(shù)入口sys.argv,python todo.py add "內(nèi)容"
數(shù)據(jù)統(tǒng)計匯總計算、格式化輸出

九、知識結(jié)構(gòu)圖

十、工程原則

  1. 數(shù)據(jù)結(jié)構(gòu)先行:先確定 JSON 存儲結(jié)構(gòu),再寫代碼——改數(shù)據(jù)結(jié)構(gòu)代價很高,中途發(fā)現(xiàn)結(jié)構(gòu)不對再改會推翻很多代碼。
  2. 每個功能一個函數(shù)add_todolist_todos、complete_todo、delete_todo 各司其職,主循環(huán)只負(fù)責(zé)分發(fā)任務(wù),不寫具體邏輯。
  3. 每次修改立即保存:這個工具的數(shù)據(jù)量極?。◣装贄l),每次操作后保存沒有性能問題,卻能保證程序崩潰時數(shù)據(jù)不丟失。
  4. 異常處理分散到各處,而非集中load_todos 處理文件不存在,main 的循環(huán)處理用戶輸入格式錯誤和強(qiáng)制退出——每個場景獨(dú)立處理,不需要一個大 try 包住整個程序。
  5. 用字典做分支映射:菜單選項 → 函數(shù)映射是一個值得養(yǎng)成的習(xí)慣——加新選項只需要在字典里加一行,主循環(huán)保持整潔。

到這里,從變量到函數(shù),從數(shù)據(jù)結(jié)構(gòu)到文件操作,從異常處理到模塊化設(shè)計——這一路走下來,已經(jīng)具備了獨(dú)立編寫小型 Python 程序的能力。

到此這篇關(guān)于使用Python編寫一個待辦事項管理器(CLI 版)的文章就介紹到這了,更多相關(guān)Python待辦事項管理器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何在django中運(yùn)行scrapy框架

    如何在django中運(yùn)行scrapy框架

    這篇文章主要介紹了如何在django中運(yùn)行scrapy框架,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Python使用Gzip解壓的示例詳解

    Python使用Gzip解壓的示例詳解

    Python?中構(gòu)建了許多用于壓縮和解壓縮目的的庫,本文為大家介紹的Gzip庫就是一種流行的數(shù)據(jù)壓縮工具,下面我們就來看看如何使用?gzip?解壓縮來解壓縮壓縮內(nèi)容吧
    2023-11-11
  • Pandas?合并數(shù)據(jù)集merge?和?join的使用

    Pandas?合并數(shù)據(jù)集merge?和?join的使用

    Pandas?提供了一個重要的功能,即高性能的內(nèi)存中連接(join)和合并(merge)操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-06-06
  • python抽取指定url頁面的title方法

    python抽取指定url頁面的title方法

    今天小編就為大家分享一篇python抽取指定url頁面的title方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • 啥是佩奇?使用Python自動繪畫小豬佩奇的代碼實(shí)例

    啥是佩奇?使用Python自動繪畫小豬佩奇的代碼實(shí)例

    今天小編就為大家分享一篇關(guān)于啥是佩奇?使用Python自動繪畫小豬佩奇的代碼實(shí)例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • pygame+opencv實(shí)現(xiàn)讀取視頻幀的方法示例

    pygame+opencv實(shí)現(xiàn)讀取視頻幀的方法示例

    由于pygame.movie.Movie.play()只支持MPEG格式的視頻,所以決定使用與opencv讀取視頻幀的畫面,本文就詳細(xì)的介紹了pygame+opencv實(shí)現(xiàn)讀取視頻幀,感興趣的可以了解一下
    2021-12-12
  • python正則表達(dá)式之作業(yè)計算器

    python正則表達(dá)式之作業(yè)計算器

    這篇文章主要為大家詳細(xì)介紹了python正則表達(dá)式之作業(yè)計算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們
    2016-03-03
  • python 批量壓縮圖片的腳本

    python 批量壓縮圖片的腳本

    用Python編寫的批量壓縮圖片的腳本,可以自定義壓縮質(zhì)量,有批量圖片壓縮需求的朋友可以直接拿來用
    2021-06-06
  • Python函數(shù)元數(shù)據(jù)實(shí)現(xiàn)為一個參數(shù)指定多個類型

    Python函數(shù)元數(shù)據(jù)實(shí)現(xiàn)為一個參數(shù)指定多個類型

    這篇文章主要介紹了Python函數(shù)元數(shù)據(jù)實(shí)現(xiàn)為一個參數(shù)指定多個類型方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • django之狀態(tài)保持-使用redis存儲session的例子

    django之狀態(tài)保持-使用redis存儲session的例子

    今天小編就為大家分享一篇django之狀態(tài)保持-使用redis存儲session的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07

最新評論

来安县| 嘉义市| 讷河市| 门源| 镇平县| 巨鹿县| 吉林市| 天等县| 台湾省| 淳化县| 色达县| 威信县| 攀枝花市| 宁都县| 吉安县| 远安县| 雷波县| 海伦市| 大同市| 新乡县| 镇巴县| 昌江| 定襄县| 临沧市| 开封县| 金华市| 黑山县| 炎陵县| 隆化县| 东城区| 陆河县| 浦北县| 阜新| 磴口县| 高要市| 盐亭县| 新化县| 贞丰县| 岳阳县| 和田县| 武安市|