资讯详情

资讯详情

用 AGENTS.md 约定驱动 Python CLI 开发:expense-report 的 Decimal 货币处理与标准库风格实践

示例工程教程【免费下载链接】materialsBonus materials, exercises, and example projects for our Python tutorials项目地址https://gitcode.com/gh_mirrors/ma/materials点击查看免费下载本指南以 expense-report 项目中的AGENTS.md约定文件为骨架讲解一份面向 AI 编码助手的项目约定应如何描述一个小型命令行工具的核心纪律货币金额一律用decimal.Decimal而非float、展示前量化到两位小数、函数保持小而单一、仅依赖标准库。读者阅读本文后既能读懂这份 14 行约定文件背后的技术动机也能对照 transactions.py 的实际实现掌握用 Decimal 重构货币计算、拆分过载函数、补齐边界处理的具体写法并学会把约定转化为 Agent 可执行的验收清单。一、约定文件的定位Agent 进入项目的第一份上下文AGENTS.md是 AI 编码助手如 Google Antigravity CLI、Claude Code 等在开始修改代码前优先读取的项目说明文件。它不面向人类文档读者而是面向模型用最简短的句子告诉 Agent这个项目是什么、什么能做、什么绝不能做。完整内容只有三部分# Project conventions This is a small command-line tool that reads a CSV of personal transactions and prints a per-category expense summary. ## Money - Represent every monetary amount with decimal.Decimal, never float. - Quantize money to exactly two decimal places before displaying it. ## Style - Keep functions small and single-purpose. - Standard library only. No third-party dependencies.三句话分别回答了 Agent 最关心的三个问题项目领域读 CSV、输出分类支出汇总、数据纪律货币精度、代码风格函数粒度与依赖边界。这种领域 硬约束 风格的组织方式并非个例本仓库中其他项目的AGENTS.md也遵循相似结构例如 agents-md/AGENTS.md 按 Project Domain、Project Setup and Management、Coding Conventions、Quality Gates、Constraints 分区要求mypy、ruff、pytest 全部通过才算完成任务python-project-for-agentic-coding/AGENTS.md 则给出uv run mypy .、uv run ruff check .、uv run pytest、uv run pre-commit run --all-files这一套可执行的开发工作流。对比可见expense-report 的约定文件更精简但同样遵循约定必须可执行、可验证的原则——这正是下文要展开的内容。二、项目本体读取 CSV、按类别输出支出汇总的 CLI先看约定文件描述的对象本身。根据 README.md这是一个从 CSV 文件汇总个人交易记录的微型命令行工具唯一的使用方式是$ python cli.py transactions.csv入口实现位于 cli.py从sys.argv[1]读取 CSV 路径缺省时回退到transactions.csv然后把结果交给report()打印。核心逻辑全部收敛在 transactions.py 的report(path)函数中处理流程可以拆成四步读取用标准库csv.DictReader逐行解析 CSV得到字典列表聚合按row[category]累加row[amount]同时累计总额与交易条数排序与占比按类别金额降序排序计算每类占总金额的百分比格式化用 f-string 输出左对齐 14 字符的类别名、右对齐 10 字符的金额和百分比最后输出TOTAL与交易条数。示例数据 transactions.csv 的表头为date,category,description,amount包含 10 条 2026 年 1 月的个人交易Groceries、Transport、Dining、Utilities 四类。实际运行输出如下$ python cli.py transactions.csv Expense report Groceries 76.79999999999998 (31.4%) Utilities 64.3 (26.3%) Transport 58.75 (24.0%) Dining 44.6 (18.2%) -------------------------------- TOTAL 244.45000000000002 10 transactions注意输出中出现了76.79999999999998、244.45000000000002这类不干净的数字——这正是约定文件里 Money 一条要解决的问题。三、Money 约定为什么永远用 Decimal绝不用 float约定文件第二条是全文最硬核的纪律Represent every monetary amount withdecimal.Decimal, neverfloat.Quantize money to exactly two decimal places before displaying it.3.1 违反约定会看到什么对照源码可以发现当前实现 transactions.py 恰恰用的是floatamount float(row[amount])累加也是totals[category] amount。上一节的运行输出就是直接后果——二进制浮点数无法精确表示12.10 8.20 53.40 3.10中间过程的舍入误差累积成76.79999999999998总和也变成了244.45000000000002。这在记账场景是不可接受的账单上永远不会出现76.79999999999998 元。误差来自 IEEE 754 双精度浮点的二进制表示0.1在二进制下是无限循环小数叠加、比较、传输都会逐级放大。约定文件要求绝不用 float正是从源头上消灭这类误差。3.2 符合约定的实现方式按约定改造的核心只有三点import csv from decimal import Decimal, ROUND_HALF_UP def read_transactions(path): 读取 CSV返回交易字典列表。 with open(path, newline) as f: return list(csv.DictReader(f)) def total_by_category(rows): 按类别累加金额全程使用 Decimal。 totals {} for row in rows: category row[category] amount Decimal(row[amount]) # 解析即转 Decimal totals[category] totals.get(category, Decimal(0)) amount return totals展示环节再补上量化quantizecents Decimal(0.01) display totals[category].quantize(cents, roundingROUND_HALF_UP)解析时Decimal(row[amount])直接把字符串转成十进制数不做中间浮点转换累加时初始值用Decimal(0)不要用Decimal(0)后者会先走一遍浮点展示时quantize(Decimal(0.01))强制四舍五入到分两位小数ROUND_HALF_UP采用与日常记账一致的四舍五入而非银行家舍入。这样重构后Groceries 一行会稳定输出76.80TOTAL 输出244.45每个金额都精确到分。约定文件没有规定排序、占比、空数据处理等细节但展示前量化这一条保证了任何派生数字百分比之外的金额列都满足两位小数的显示契约。四、Style 约定小而单一的函数与零第三方依赖Keep functions small and single-purpose.Standard library only. No third-party dependencies.4.1 从源码结构看单一日志函数为什么需要拆分对照 transactions.py 的report()一个函数里同时承担了文件 IO、CSV 解析、类别聚合、占比计算、字符串排版、总额与条数统计。从源码结构可以推断这正是约定文件说keep functions small and single-purpose时希望避免的形态——职责太多会导致难以单独测试聚合逻辑、难以复用占比算法、改动排版时必须碰 IO 与数据逻辑。按约定可以拆成三个各司其职的小函数与 3.2 节的示例衔接def report(path): rows read_transactions(path) # 1. 读 totals total_by_category(rows) # 2. 聚合 grand_total sum(totals.values(), Decimal(0)) return format_report(totals, grand_total, len(rows)) # 3. 排版read_transactions(path)只负责把 CSV 变成数据total_by_category(rows)只负责按类别聚合与 IO 解耦format_report(totals, grand_total, count)只负责排版输出可单独喂入构造数据做单元测试。4.2 仅标准库意味着什么csv、decimal、sys全部来自 Python 标准库cli.py和transactions.py没有任何import requests、import pandas之类的第三方依赖项目也不需要requirements.txt或虚拟环境。这对 AI 编码助手是极大的确定性红利任何安装了 CPython 的环境都能直接python cli.py transactions.csv运行Agent 无需先解决依赖安装、版本冲突、网络拉包等问题。约定文件用一句话锁死了依赖边界——后续任何 Agent 想引入第三方库都必须先与人类确认这正是 agents-md/AGENTS.md 中Ask before adding any external dependency同款的护栏。五、边界与可运行性把约定翻译成 Agent 的验收清单约定文件本身没有写测试和边界处理但仓库提供了第二个数据文件 transactions_zero.csv表头为date,category,amount两行数据Refunds, -50.00与Purchases, 50.00恰好互相抵消。实际运行$ python cli.py transactions_zero.csv会触发report()第 29 行share totals[category] / grand_total * 100的ZeroDivisionError: float division by zero——因为此时grand_total为0.0。这是一个真实的边界缺陷也说明约定文件只约束了怎么算钱没有约束算不出时怎么办。一份更完备的 AGENTS.md 可以在原有约定基础上补一条可执行的验收清单让 Agent 在交付前自查运行python cli.py transactions.csv应输出四个类别及TOTAL 244.45金额精确到分运行python cli.py transactions_zero.csv不得抛出ZeroDivisionError应输出总额为 0 的报告或给出明确提示搜索全部源码float不得出现在任何金额计算路径中import语句仅允许来自标准库每个函数不超过 20 行、只承担单一职责。这种可运行命令 可观察结果的写法与 python-project-for-agentic-coding/AGENTS.md 中Run the full test suite after modifying code的思路一脉相承约定如果不能被命令验证Agent 就无法判断自己是否做对了。六、小结约定文件如何让 AI 协作更可控回到 AGENTS.md 本身这份文件的可贵之处在于每条约定都对应可观察的代码事实约定条款对应的代码事实违反时的可见后果用Decimal不用floattransactions.py 当前用float(row[amount])输出76.79999999999998、244.45000000000002展示前量化到两位小数quantize(Decimal(0.01))应在格式化前调用金额列出现超过两位小数的尾数函数小而单一report()同时承担 IO、聚合、排版无法独立测试聚合与排版逻辑仅标准库import csv / decimal / sys环境依赖不可控无法直接运行对 AI 编码助手而言这样的约定文件就是需求说明书 验收标准它不需要读懂整份业务代码只要遵守四条规则就能在保持项目风格一致的前提下安全地增删功能对人类维护者而言它把最容易出错的货币精度问题变成了一道显式关卡。若要让这份约定进一步进化方向是补充边界规则空数据、零总额、缺失列与可执行的质量门槛——届时AGENTS.md就能像本仓库其他项目那样成为 Agent 与人类之间一份真正可验收的工程契约。赞分享示例工程教程【免费下载链接】materialsBonus materials, exercises, and example projects for our Python tutorials项目地址https://gitcode.com/gh_mirrors/ma/materials点击查看免费下载相关推荐如何用测试驱动开发打造健壮的Money Ruby库从小白到专家的完整指南如何用测试驱动开发打造健壮的Money Ruby库从小白到专家的完整指南 Money Ruby库是一个强大的Ruby货币处理工具能够轻松处理货币计算和转换。shadcn/ui主题完全指南10分钟打造个性化界面shadcn/ui主题完全指南10分钟打造个性化界面 shadcn/ui主题完全指南提供了快速掌握10000主题使用的方法帮助开发者在10分钟内打造出独具MoneyPHPPHP中的货币处理库MoneyPHPPHP中的货币处理库 项目基础介绍和主要编程语言 MoneyPHP是一个用PHP编写的开源库旨在提供一个安全、简单且有趣的货币处理解决方案。后端上一篇探索NooBox一款创新的智能化工具箱下一篇【亲测免费】 BIThesis一站式的毕业论文管理利器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →