所有入門單元免費開放 · 課程內容持續更新中

行動練習:做一個記帳小工具

把前面學到的變數、條件、迴圈、函式、串列和字典全部串起來,一步一步做出一個會把資料存成 CSV 的記帳小工具。

第 1.7 堂約 18 分鐘

這一堂,你要做出真的能用的東西

前面六堂課,你學了一塊一塊的積木。這一堂要把它們組起來,做一個你明天就能開始用的記帳工具:

  • 在終端機輸入類別、項目、金額,記下一筆花費
  • 資料存在 expenses.csv,關掉程式再打開,紀錄還在
  • 隨時看各類別的小計和總計

完成後大約 60 行(含空行)。別擔心,我們會一段一段來,每一段都是你學過的東西。

先規劃,再寫程式

動手之前,先想清楚兩件事。這也是你之後請 AI 寫程式前,最該先想好的部分。

資料長什麼樣子? 一筆花費是一個字典,所有紀錄是「字典組成的串列」,和上一堂一模一樣:

{"date": "2026-11-07", "category": "餐費", "item": "雞腿便當", "amount": 85}

需要哪些功能? 每個功能各寫一個函式:

函式 負責的事
load_records 程式開啟時,從 CSV 讀入舊紀錄
save_records 把所有紀錄寫回 CSV
ask_amount 問金額,確定是數字(第 5 堂寫過)
add_record 記一筆新的花費
show_report 依類別加總並印出報表
main 顯示選單,依照選擇呼叫上面的函式

程式架構圖:main 選單呼叫 add_record 和 show_report,add_record 使用 ask_amount 並呼叫 save_records 寫入 expenses.csv,程式開始時 load_records 從 expenses.csv 讀入資料

每個方塊都是一個函式,各自只做一件事。

第一步:準備工作

在你的練習資料夾建立 expense.py,最上面先寫:

import csv
from datetime import date
from pathlib import Path

FILE = Path("expenses.csv")
FIELDS = ["date", "category", "item", "amount"]

import 是「借用 Python 內建的工具箱」:csv 負責讀寫 CSV,date 用來拿今天的日期,Path 用來代表一個檔案路徑。

全大寫的變數名稱是一種習慣,意思是「這是設定值,程式執行中不會改它」。

第二步:讀檔與存檔

def load_records():
    if not FILE.exists():
        return []
    with FILE.open(encoding="utf-8-sig", newline="") as f:
        records = list(csv.DictReader(f))
    for r in records:
        r["amount"] = int(r["amount"])
    return records


def save_records(records):
    with FILE.open("w", encoding="utf-8-sig", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=FIELDS)
        writer.writeheader()
        writer.writerows(records)

幾個新東西,一次說明:

  • with ... as f:打開檔案,縮排裡的程式跑完後會自動關檔。就算中途出錯也會關好,不會讓檔案卡住。
  • csv.DictReader:把 CSV 的每一列讀成一個字典,鍵就是第一列的欄位名稱。正好是我們要的格式。
  • int(r["amount"]):還記得第 3 堂的坑嗎?從檔案讀出來的東西都是字串,要計算前得轉成數字。
  • "w":寫入模式,會用新內容整個覆蓋舊檔案。

寫到這裡,先別急著往下。這兩個函式還沒被呼叫,執行程式不會有任何反應,這是正常的。

第三步:記一筆和看報表

def ask_amount(question):
    while True:
        text = input(question)
        if text.isdigit():
            return int(text)
        print("請輸入阿拉伯數字,例如 85")


def add_record(records):
    category = input("類別(例如 餐費、交通):")
    item = input("項目:")
    amount = ask_amount("金額:")
    records.append({"date": date.today().isoformat(), "category": category,
                    "item": item, "amount": amount})
    save_records(records)
    print("已記下!")


def show_report(records):
    if not records:
        print("還沒有任何紀錄")
        return
    by_category = {}
    for r in records:
        cat = r["category"]
        by_category[cat] = by_category.get(cat, 0) + r["amount"]
    for cat, subtotal in by_category.items():
        print(f"{cat}:{subtotal} 元")
    print(f"總計:{sum(by_category.values())} 元")

ask_amount 直接沿用第 5 堂的版本。show_report 的加總邏輯就是第 6 堂的「依類別加總」。.items() 會同時給你每個鍵和值,.values() 只給值。

date.today().isoformat() 會產生像 2026-11-07 這樣的日期字串。每記一筆就馬上存檔,就算你直接關掉視窗,資料也不會遺失。

第四步:選單,把一切串起來

def main():
    records = load_records()
    print(f"已讀入 {len(records)} 筆紀錄")
    while True:
        choice = input("\n1 記一筆 2 看報表 q 離開:")
        if choice == "1":
            add_record(records)
        elif choice == "2":
            show_report(records)
        elif choice == "q":
            print("掰掰,明天也要記帳喔!")
            break
        else:
            print("請輸入 1、2 或 q")


main()

break 會立刻跳出 while 迴圈,程式就結束了。字串裡的 \n 代表換行,讓選單前面空一行比較好讀。

把四個步驟的程式依序貼在同一個檔案裡,執行看看:

python expense.py

終端機示意圖:執行 expense.py 後顯示已讀入 0 筆紀錄,選 1 記下雞腿便當 85 元,選 2 看到餐費 85 元與總計,選 q 離開

記幾筆之後,到資料夾裡找到 expenses.csv,用 Excel 或 VS Code 打開,你會看到自己的資料整整齊齊地排好。

卡住了怎麼辦

最常見的三種狀況:

  • IndentationError:貼上程式時縮排亂掉了。每個 def 底下的內容都要往右 4 格。
  • NameError: name 'xxx' is not defined:通常是打錯字,或函式的順序不對。main() 這一行一定要放在最後面。
  • KeyError: 'amount':CSV 第一列的欄位名稱被改過了。刪掉 expenses.csv 讓程式重建即可(記帳資料會一起清空,先備份)。
可以這樣問 Claude

我在做一個 Python 的記帳小工具,執行時出現下面的錯誤。我是初學者,請告訴我:1)這個錯誤是什麼意思;2)最可能是我程式的哪一行出問題;3)怎麼修。請不要整份重寫,只指出要改的地方。

錯誤訊息:(完整貼上)

我的程式:(完整貼上)

「不要整份重寫,只指出要改的地方」這句很重要。這樣你才知道問題出在哪,下次就會自己修。

行動練習
  1. 照著四個步驟完成 expense.py,記下你今天真實的 3 筆花費,再用 Excel 打開 expenses.csv 確認。
  2. 加一個新功能:選單多一個 3 看最近 5 筆,印出最後 5 筆紀錄的日期、項目和金額。(提示:還記得串列的負數索引嗎?records[-5:] 可以拿到最後 5 筆。)
  3. 挑戰:自己先想好怎麼做,再請 Claude 幫你加上「只看本月份」的報表功能。拿到程式後,先讀懂每一行,再執行驗收。

恭喜你完成了這個單元。你已經能讀懂並寫出一支真的派得上用場的程式了。

讀完了嗎?

標記完成後,單元與專案的進度會自動更新(只存在這台裝置的瀏覽器)。

卡住了?讓 AI 當你的家教複製這段提問範本,貼到 Claude 或其他 AI 工具,再補上你卡住的地方。

留言與討論

卡關了、有心得,或發現內容需要更新?都歡迎留言。留言使用 GitHub 帳號登入。

留言區即將開放。現在可以先到 GitHub 討論區 發問,或看看 交流頁 的其他管道。