前言
如果你是从上一篇《大一新生 × AI Coding:从概念到实践,我如何用DeepSeek做出第一个Python游戏》过来的,那么恭喜你,你已经拥有了和计算机“对话”的初级能力。
今天我们趁热打铁,来做一个更贴近生活的实用小工具——命令行记账本
它能帮你记录每天的收支、自动计算余额,而且数据会保存在文件里,关机再开也不会丢。
全程依然是零基础友好,你只需要跟着我一步步操作,你的第二个 Python 项目就能跑起来。


一、项目功能说明
这个命令行记账本支持以下操作:

  1. 记录收入:输入金额和说明(比如“生活费 +2000”)

  2. 记录支出:输入金额和说明(比如“奶茶 -15”)

  3. 查看当前余额:自动计算总收入减去总支出

  4. 查看所有收支明细:按时间顺序列出每一笔账

  5. 数据自动保存到文件account_book.json

  6. 启动时自动加载历史数据,关掉程序再打开,账本还在

运行起来的主菜单长这样:

========== 简易记账本 ==========

  1. 记录收入

  2. 记录支出

  3. 查看余额

  4. 查看明细

  5. 退出
    请选择操作(1-5):

是不是感觉像个真正的软件了?实际上它的核心代码只有不到 100 行。


二、实现思路
我们用一种“先想清楚再动手”的方式来拆解这个项目:

  • 数据存储:用 Python 的列表(list)来装所有记录,每一条记录是一个字典(dict),包含:类型、金额、说明、时间。

  • 文件保存:用 JSON 格式把列表存到文件里(account_book.json),下次启动时读回来。JSON 的好处是人和机器都能看懂。

  • 主程序结构:一个 while True 无限循环,显示菜单,根据用户输入的数字调用不同的函数。

  • 余额计算:遍历所有记录,收入就加,支出就减。

这种“数据 + 操作”的模式,其实就是最朴素的编程思维。


三、第一步:搭建 Python 环境(已有可跳过)
如果你已经跟着第一篇装好了 Python,打开命令提示符输入 python --version 能正常显示版本号,那就可以直接跳到下一步。
如果你还没装,或者不确定,请回到上一篇的 “三、第一步:搭建 Python 环境” 部分,跟着截图一步步安装,几分钟就能搞定。


四、第二步:创建项目文件
我们需要新建一个 .py 文件来装记账本的代码。

  1. 在桌面空白处右键 → 新建 → 文本文档

  2. 确保能看到文件扩展名(如果看不到 .txt,打开任意文件夹 → 顶部“查看” → 勾选“文件扩展名”)

  3. 把 新建文本文档.txt 重命名为 account_book.py
    ⚠️ 注意:后缀一定要从 .txt 变成 .py,系统会提示“改变扩展名可能导致文件不可用”,点“是”就行。


五、第三步:向 DeepSeek 提问,生成初版代码
打开 DeepSeek(网页版或 App 都可以),选择专家模式,然后把下面这段话复制进去:

用Python写一个命令行记账本程序,功能包括:

  1. 记录收入(输入金额和说明)

  2. 记录支出(输入金额和说明)

  3. 查看当前余额

  4. 查看所有收支明细

  5. 数据保存在JSON文件中,下次启动时自动加载
    代码要附带详细注释,适合初学者阅读。

DeepSeek 会很快返回一段完整的代码。全选复制,然后我们把它粘贴到 account_book.py 里。

下面是它生成的核心代码(你可以直接对照检查):

text

"""
简单命令行记账本程序
功能:
- 记录收入(金额 + 说明)
- 记录支出(金额 + 说明)
- 查看当前余额
- 查看所有收支明细
- 数据自动保存到 JSON 文件,下次启动时自动加载
"""

import json
import os
from datetime import datetime


class Ledger:
    """记账本类,负责管理收支记录和文件读写"""

    def __init__(self, filename="ledger_data.json"):
        """
        初始化记账本
        :param filename: 保存数据的 JSON 文件名
        """
        self.filename = filename
        self.transactions = []  # 存储所有收支记录的列表,每条记录是一个字典
        self.load_data()        # 启动时加载已有数据

    def load_data(self):
        """从 JSON 文件加载历史数据,如果文件不存在则忽略"""
        if os.path.exists(self.filename):
            try:
                with open(self.filename, "r", encoding="utf-8") as f:
                    self.transactions = json.load(f)
                print(f"已加载历史数据,共 {len(self.transactions)} 条记录。")
            except (json.JSONDecodeError, IOError):
                print("数据文件损坏或无法读取,将使用空账本。")
                self.transactions = []
        else:
            print("未找到历史数据文件,将创建新账本。")

    def save_data(self):
        """将当前所有交易记录保存到 JSON 文件"""
        try:
            with open(self.filename, "w", encoding="utf-8") as f:
                json.dump(self.transactions, f, ensure_ascii=False, indent=4)
            print("数据已保存。")
        except IOError as e:
            print(f"保存数据时出错:{e}")

    def add_income(self, amount, description):
        """
        添加一笔收入记录
        :param amount: 收入金额(正数)
        :param description: 收入说明
        """
        if amount <= 0:
            print("错误:收入金额必须大于0。")
            return
        if not description.strip():
            print("错误:说明不能为空。")
            return

        # 创建一条记录,包含类型、金额、说明和时间戳
        transaction = {
            "type": "income",
            "amount": amount,
            "description": description.strip(),
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        self.transactions.append(transaction)
        self.save_data()
        print(f"收入记录已添加:+{amount:.2f} 元,说明:{description}")

    def add_expense(self, amount, description):
        """
        添加一笔支出记录
        :param amount: 支出金额(正数)
        :param description: 支出说明
        """
        if amount <= 0:
            print("错误:支出金额必须大于0。")
            return
        if not description.strip():
            print("错误:说明不能为空。")
            return

        transaction = {
            "type": "expense",
            "amount": amount,
            "description": description.strip(),
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        self.transactions.append(transaction)
        self.save_data()
        print(f"支出记录已添加:-{amount:.2f} 元,说明:{description}")

    def get_balance(self):
        """
        计算当前余额:总收入 - 总支出
        :return: 余额(浮点数)
        """
        total_income = sum(t["amount"] for t in self.transactions if t["type"] == "income")
        total_expense = sum(t["amount"] for t in self.transactions if t["type"] == "expense")
        return total_income - total_expense

    def show_balance(self):
        """在控制台打印当前余额"""
        balance = self.get_balance()
        print(f"\n当前余额:{balance:.2f} 元\n")

    def show_transactions(self):
        """在控制台按时间顺序打印所有收支明细"""
        if not self.transactions:
            print("\n还没有任何收支记录。\n")
            return

        print("\n========== 所有收支明细 ==========")
        # 按时间顺序显示(记录添加的顺序)
        for idx, t in enumerate(self.transactions, start=1):
            type_str = "收入" if t["type"] == "income" else "支出"
            sign = "+" if t["type"] == "income" else "-"
            print(f"{idx}. [{t['timestamp']}] {type_str}: {sign}{t['amount']:.2f} 元")
            print(f"   说明:{t['description']}")
        print("==================================\n")


def show_menu():
    """显示主菜单选项"""
    print("========== 简单记账本 ==========")
    print("1. 记录收入")
    print("2. 记录支出")
    print("3. 查看当前余额")
    print("4. 查看所有收支明细")
    print("5. 退出程序")
    print("================================")


def get_positive_float(prompt):
    """
    获取用户输入的正浮点数(金额)
    如果输入无效或非正数,则提示重新输入
    """
    while True:
        try:
            value = float(input(prompt))
            if value <= 0:
                print("金额必须大于0,请重新输入。")
                continue
            return value
        except ValueError:
            print("输入无效,请输入一个数字。")


def main():
    """主程序入口,处理用户交互"""
    ledger = Ledger()  # 创建账本实例,自动加载历史数据

    while True:
        show_menu()
        choice = input("请输入选项(1-5):").strip()

        if choice == "1":
            # 记录收入
            amount = get_positive_float("请输入收入金额:")
            description = input("请输入收入说明:").strip()
            ledger.add_income(amount, description)

        elif choice == "2":
            # 记录支出
            amount = get_positive_float("请输入支出金额:")
            description = input("请输入支出说明:").strip()
            ledger.add_expense(amount, description)

        elif choice == "3":
            # 查看余额
            ledger.show_balance()

        elif choice == "4":
            # 查看明细
            ledger.show_transactions()

        elif choice == "5":
            # 退出程序
            print("感谢使用,再见!")
            break

        else:
            print("无效选项,请输入 1-5 之间的数字。")


if __name__ == "__main__":
    main()

如何把代码放进文件?

  1. 右键点击桌面上的 account_book.py → 打开方式 → 记事本

  2. 把上面复制下来的代码粘贴进去

  3. 按 Ctrl+S 保存,然后关闭记事本

搞定!现在你的第一个记账本程序就已经“写”好了。


六、第四步:运行程序
和上次运行猜数字游戏一样,我们在命令行里启动它。

  1. 确保 account_book.py 文件在桌面上。

  2. 在桌面空白处,按住键盘上的 Shift 键不放,同时点击鼠标右键。

  3. 在弹出的菜单里选择 “在此处打开 PowerShell 窗口”(Win10/11)或 “在此处打开命令窗口”

  4. 在打开的蓝色或黑色窗口中输入以下命令,然后按回车:

text

python account_book.py

如果一切顺利,你会立刻看到主菜单:

========== 简易记账本 ==========

  1. 记录收入

  2. 记录支出

  3. 查看余额

  4. 查看明细

  5. 退出
    请选择操作(1-5):


七、第五步:实际使用演示 + 数据持久化验证
现在我们来真实地记两笔账,看看效果。

操作过程

  1. 输入 1,记录收入:

    • 金额:2000

    • 说明:生活费

  2. 输入 2,记录支出:

    • 金额:35.5

    • 说明:买奶茶

  3. 输入 3,查看余额,显示:当前余额:1964.50 元

  4. 输入 4,查看明细,显示:

========== 收支明细 ==========
[2026-04-10 14:20:15] 收入 2000.00 元 说明:生活费
[2026-04-10 14:21:03] 支出 35.50 元 说明:买奶茶
==============================

  1. 输入 5,退出程序。

关键验证:数据真的保存了吗?
关掉命令行窗口,然后再次运行 python account_book.py。进入程序后直接按 4 查看明细——你会发现刚才的记录完完整整还在那里

这是因为程序在同目录下生成了一个 account_book.json 文件,你可以用记事本打开它看看:

text

[
  {
    "type": "收入",
    "amount": 2000.0,
    "desc": "生活费",
    "time": "2026-04-10 14:20:15"
  },
  {
    "type": "支出",
    "amount": 35.5,
    "desc": "买奶茶",
    "time": "2026-04-10 14:21:03"
  }
]

这种关了再开数据还在的能力,在编程里叫数据持久化。这也是我们这个记账本区别于上一篇猜数字游戏的最大进步。


八、第六步:迭代改进——增加删除记录功能(可选)
用了一天后,我发现一个问题:万一我不小心输错了金额,想删掉某条记录怎么办?现在还没有删除功能。

于是我又打开 DeepSeek,输入了新的需求:

请在上面的记账本代码中增加一个功能:删除记录。
用户选择删除后,先展示所有记录并编号,然后让用户输入要删除的编号,确认后删除对应记录并保存。

DeepSeek 很快给出了修改方案。主要改动是:

  1. 在主菜单增加选项 6. 删除记录

  2. 新增一个 delete_record() 函数,用来展示带编号的记录并处理删除逻辑

核心代码片段大概是这样(你可以让 AI 生成完整版):

text

def delete_record():
    if not records:
        print("暂无记录可删除。")
        return
    print("\n========== 当前记录 ==========")
    for i, r in enumerate(records, start=1):
        print(f"{i}. [{r['time']}] {r['type']} {r['amount']} 元  {r['desc']}")
    print("================================")
    try:
        num = int(input("请输入要删除的记录编号(输入0取消):"))
        if num == 0:
            return
        if 1 <= num <= len(records):
            deleted = records.pop(num - 1)
            save_data()
            print(f"已删除记录:{deleted['desc']} {deleted['amount']} 元")
        else:
            print("编号超出范围!")
    except ValueError:
        print("输入无效,请输入数字编号。")

你可以自己尝试把这个功能加到完整代码里。如果遇到报错,直接把错误信息复制给 DeepSeek,它会帮你改好。这也是 AI Coding 最好用的地方——它不仅是代码生成器,还是你的专属 debug 助手。


九、我学到了什么
从猜数字游戏到命令行记账本,我感觉自己好像升级了。这次我新掌握的东西包括:

  • 文件操作open()json.load()json.dump(),知道怎么让数据“永久保存”。

  • 结构化数据:列表里套字典,用起来非常灵活。

  • 异常处理try...except 防止用户乱输入导致程序崩溃。

  • 模块化编程:一个功能一个函数,主函数只负责调度,代码清晰多了。

  • 真实的开发流程:想功能 → 问 AI → 跑起来 → 发现问题 → 再问 AI 改进。

更重要的是,我开始理解编程不是背语法,而是用工具解决实际问题。AI 帮我跳过了那些让人头疼的语法细节,让我能直接看到成果,保持学习的动力。


十、下一步计划
目前我们已经有了两个命令行小工具:猜数字 + 记账本。接下来我想挑战一个带图形界面的程序

Python 自带一个叫 tkinter 的库,可以轻松做出窗口、按钮、输入框。我打算用它做一个简单的计算器,或者一个备忘录。

等做出来了,我会继续写成第三篇博客。如果你跟着做到了这里,不妨在评论区告诉我,你的第二个 Python 项目跑起来了吗?遇到什么坑没有?

我们一起进步!


附录:完整代码(记账本基础版)

text

import json
import os
from datetime import datetime

DATA_FILE = "account_book.json"
records = []

def load_data():
    global records
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE, 'r', encoding='utf-8') as f:
            records = json.load(f)
    else:
        records = []

def save_data():
    with open(DATA_FILE, 'w', encoding='utf-8') as f:
        json.dump(records, f, ensure_ascii=False, indent=2)

def add_income():
    try:
        amount = float(input("请输入收入金额:"))
        if amount <= 0:
            print("金额必须大于0!")
            return
        desc = input("请输入收入说明:")
        record = {
            "type": "收入",
            "amount": amount,
            "desc": desc,
            "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        records.append(record)
        save_data()
        print("收入记录已保存!")
    except ValueError:
        print("输入错误,请输入有效的数字!")

def add_expense():
    try:
        amount = float(input("请输入支出金额:"))
        if amount <= 0:
            print("金额必须大于0!")
            return
        desc = input("请输入支出说明:")
        record = {
            "type": "支出",
            "amount": amount,
            "desc": desc,
            "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        records.append(record)
        save_data()
        print("支出记录已保存!")
    except ValueError:
        print("输入错误,请输入有效的数字!")

def show_balance():
    total = 0
    for r in records:
        if r["type"] == "收入":
            total += r["amount"]
        else:
            total -= r["amount"]
    print(f"当前余额:{total:.2f} 元")

def show_details():
    if not records:
        print("暂无任何记录。")
        return
    print("\n========== 收支明细 ==========")
    for r in records:
        print(f"[{r['time']}] {r['type']}  {r['amount']:.2f} 元  说明:{r['desc']}")
    print("==============================\n")

def main():
    load_data()
    while True:
        print("\n========== 简易记账本 ==========")
        print("1. 记录收入")
        print("2. 记录支出")
        print("3. 查看余额")
        print("4. 查看明细")
        print("5. 退出")
        choice = input("请选择操作(1-5):")

        if choice == '1':
            add_income()
        elif choice == '2':
            add_expense()
        elif choice == '3':
            show_balance()
        elif choice == '4':
            show_details()
        elif choice == '5':
            print("再见!")
            break
        else:
            print("输入无效,请重新选择。")

if __name__ == "__main__":
    main()

本文代码由 DeepSeek 生成,作者已实际运行验证。

AI 声明:
本文由 DeepSeek 辅助生成代码和部分文案,所有步骤均经过本人实际操作验证。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐