**学习日期**: 2026-05-03
**项目**: 个人财务管理工具(Finance Tracker)
**预计时间**: 20分钟实践 + 30分钟理论学习
**项目定位**: Phase 1综合项目,综合运用Day 1-6所有知识
---
```python
class Transaction:
def __init__(self, amount, category, description):
self.amount = amount
self.category = category
self.description = description
self.budgets = {}
self.transactions = []
```
```python
import json
def to_dict(self):
return {
"amount": self.amount,
"category": self.category,
"date": self.date
}
@classmethod
def from_dict(cls, data):
return cls(data["amount"], data["category"], data["date"])
```
```python
from collections import defaultdict
monthly_income = defaultdict(float)
for t in transactions:
if t.type == "income":
monthly_income[t.date[:7]] += t.amount
sorted_items = sorted(items, key=lambda x: x[1], reverse=True)
```
```python
try:
amount = float(input("金额: "))
if amount <= 0:
raise ValueError("金额必须大于0")
except ValueError as e:
print(f"输入错误: {e}")
```
```python
class Transaction:
pass
class Budget:
def update_spent(self, amount):
self.spent += amount
class FinanceTracker:
def __init__(self):
self.transactions = []
self.budgets = {}
```
---
```python
from collections import defaultdict
normal_dict = {}
for item in items:
if item.category not in normal_dict:
normal_dict[item.category] = 0
normal_dict[item.category] += item.amount
default_dict = defaultdict(float)
for item in items:
default_dict[item.category] += item.amount
```
**defaultdict的工作原理**:
- 访问不存在的key时,自动调用传入的工厂函数(float → 0.0, int → 0, list → [])
- 不需要写 `if key in dict` 的判断
---
```python
from datetime import datetime, timedelta
now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S"))
future = now + timedelta(days=30)
past = now - timedelta(days=7)
date_str = "2026-05-01"
date_obj = datetime.strptime(date_str, "%Y-%m-%d")
date_str = date_obj.strftime("%Y-%m-%d")
```
```python
this_month = datetime.now().strftime("%Y-%m")
month_transactions = [t for t in transactions if t.date.startswith(this_month)]
cutoff = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
recent = [t for t in transactions if t.date >= cutoff]
```
---
```python
def show_monthly_report(self, year, month):
month_str = f"{year}-{month:02d}"
month_data = [t for t in self.transactions if t.date.startswith(month_str)]
income = sum(t.amount for t in month_data if t.type == "income")
expense = sum(t.amount for t in month_data if t.type == "expense")
by_category = defaultdict(float)
for t in month_data:
by_category[t.category] += t.amount
print(f"收入: ¥{income:,.2f}")
print(f"支出: ¥{expense:,.2f}")
for cat, amount in sorted(by_category.items(), key=lambda x: x[1], reverse=True):
print(f" {cat}: ¥{amount:,.2f}")
```
```python
def show_yearly_report(self, year):
monthly_data = defaultdict(lambda: {"income": 0, "expense": 0})
for t in self.transactions:
if t.date.startswith(str(year)):
month = t.date[5:7]
monthly_data[month][t.type] += t.amount
print(f"{'月份':<8} {'收入':>12} {'支出':>12} {'结余':>12}")
for month in sorted(monthly_data.keys()):
data = monthly_data[month]
balance = data["income"] - data["expense"]
print(f"{month}月 ¥{data['income']:>10,.2f} ¥{data['expense']:>10,.2f} ¥{balance:>10,.2f}")
```
---
```python
class Budget:
def __init__(self, category, limit):
self.category = category
self.limit = limit
self.spent = 0
def update_spent(self, amount):
self.spent += amount
def get_remaining(self):
return self.limit - self.spent
def get_percentage(self):
return (self.spent / self.limit) * 100
def is_exceeded(self):
return self.spent > self.limit
```
```python
def _get_progress_bar(self):
percentage = min(self.get_percentage(), 100)
filled = int(percentage / 5)
empty = 20 - filled
return "█" * filled + "░" * empty + f" {percentage:.1f}%"
```
---
✅ **记账功能** - 记录收入和支出
✅ **分类管理** - 预定义收入和支出分类
✅ **交易查询** - 按类型、时间筛选
✅ **月度报表** - 收支明细、分类统计、结余
✅ **年度报表** - 按月汇总、全年统计
✅ **预算管理** - 设置预算、跟踪执行、超支提醒
✅ **资产总览** - 累计收支、本月收支、最近交易
✅ **数据持久化** - JSON文件自动保存
```python
class Transaction:
"""交易记录"""
def __init__(self, amount, category, description, date, type):
self.id = datetime.now().strftime("%Y%m%d%H%M%S%f")
self.amount = amount
self.category = category
self.description = description
self.date = date
self.type = type
class Budget:
"""预算"""
def __init__(self, category, limit):
self.category = category
self.limit = limit
self.spent = 0
def update_spent(self, amount):
self.spent += amount
def is_exceeded(self):
return self.spent > self.limit
class FinanceTracker:
"""财务管理器"""
def __init__(self, data_file="finance_data.json"):
self.data_file = data_file
self.transactions = []
self.budgets = {}
self.load_data()
def add_transaction(self, amount, category, description, date, type):
"""添加交易"""
transaction = Transaction(amount, category, description, date, type)
self.transactions.append(transaction)
if type == "expense" and category in self.budgets:
self.budgets[category].update_spent(amount)
self.save_data()
def show_monthly_report(self, year, month):
"""月度报表"""
month_data = [t for t in self.transactions if t.date.startswith(f"{year}-{month:02d}")]
income = sum(t.amount for t in month_data if t.type == "income")
expense = sum(t.amount for t in month_data if t.type == "expense")
def show_budgets(self):
"""显示预算"""
for budget in self.budgets.values():
print(budget)
```
```bash
source .venv/Scripts/activate
python day07_finance_tracker.py
```
**操作菜单**:
1. 记一笔(收入/支出)
2. 查看交易记录(全部/收入/支出/最近7天/最近30天)
3. 删除记录
4. 月度报表
5. 年度报表
6. 预算管理(设置/查看)
7. 资产总览
8. 退出
---
```
┌─────────────────────────────────────────┐
│ FinanceTracker (管理器) │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ transactions│ │ budgets │ │
│ │ (list) │ │ (dict) │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ┌────▼────┐ ┌────▼────┐ │
│ │Transaction│ │ Budget │ │
│ │ - amount │ │ - limit │ │
│ │ - category│ │ - spent │ │
│ │ - date │ │ - percentage│ │
│ └─────────┘ └─────────┘ │
└─────────────────────────────────────────┘
```
---
| 天数 | 知识点 | 本项目应用 |
|------|--------|-----------|
| Day 1 | 类与对象 | Transaction, Budget, FinanceTracker |
| Day 2 | 字典操作 | budgets字典, 分类统计 |
| Day 3 | JSON序列化 | to_dict / from_dict |
| Day 4 | 数据分析 | defaultdict, 排序, 格式化 |
| Day 5 | 错误处理 | 金额验证, 异常捕获 |
| Day 6 | 继承与类方法 | 独立类设计, 工厂方法 |
| 工厂函数 | 默认值 |
|----------|--------|
| `defaultdict(int)` | 0 |
| `defaultdict(float)` | 0.0 |
| `defaultdict(list)` | [] |
| `defaultdict(dict)` | {} |
| `defaultdict(lambda: {"income": 0, "expense": 0})` | 自定义结构 |
| 功能 | 代码 |
|------|------|
| 当前时间 | `datetime.now()` |
| 格式化输出 | `dt.strftime("%Y-%m-%d")` |
| 字符串解析 | `datetime.strptime("2026-05-01", "%Y-%m-%d")` |
| 日期运算 | `dt + timedelta(days=30)` |
---
```python
monthly_data = defaultdict(lambda: {"income": 0, "expense": 0})
monthly_data["2026-03"]["income"] += 1000
```
```python
transactions = [t for t in all if t.date.startswith("2026-05")]
cutoff = "2026-05-01"
recent = [t for t in all if t.date >= cutoff]
```
**原理**:"2026-05-01" < "2026-05-02"(字符串按字典序比较,日期格式正好符合)
```python
def add_transaction(self, amount, category, type):
transaction = Transaction(amount, category, ..., type)
self.transactions.append(transaction)
if type == "expense" and category in self.budgets:
self.budgets[category].update_spent(amount)
self.save_data()
```
**设计要点**:预算更新和交易记录是原子操作,一起完成一起保存。
---
```python
from collections import defaultdict
text = "apple banana apple cherry banana apple"
words = text.split()
count = defaultdict(int)
for word in words:
count[word] += 1
print(dict(count))
```
```python
from datetime import datetime, timedelta
due = datetime.now() + timedelta(days=30)
print(due.strftime("%Y-%m-%d"))
d1 = datetime.strptime("2026-05-01", "%Y-%m-%d")
d2 = datetime.strptime("2026-05-10", "%Y-%m-%d")
diff = (d2 - d1).days
print(f"相差 {diff} 天")
```
```python
from collections import defaultdict
data = [
{"month": "2026-01", "type": "income", "amount": 5000},
{"month": "2026-01", "type": "expense", "amount": 3000},
{"month": "2026-02", "type": "income", "amount": 5500},
{"month": "2026-02", "type": "expense", "amount": 3500},
]
monthly = defaultdict(lambda: {"income": 0, "expense": 0})
for item in data:
monthly[item["month"]][item["type"]] += item["amount"]
for month, values in sorted(monthly.items()):
balance = values["income"] - values["expense"]
print(f"{month}: 结余 ¥{balance}")
```
---
- defaultdict的高级用法(lambda自定义结构)
- datetime日期处理和运算
- 复杂报表的生成方法
- 预算管理系统的设计
- 综合运用前6天所有知识
- defaultdict的工厂函数可以是任意可调用对象
- 日期字符串比较的前提是格式统一(YYYY-MM-DD)
- 预算和交易需要保持数据一致性
- ✅ 完成了Phase 1综合项目
- ✅ 实现了完整的财务管理功能
- ✅ 设计了预算跟踪系统
- ✅ 生成了月度/年度报表
- ✅ 综合运用所有Python基础知识
---
- [collections文档](https://docs.python.org/zh-cn/3/library/collections.html
- [datetime文档](https://docs.python.org/zh-cn/3/library/datetime.html)
- [Python项目结构指南](https://docs.python-guide.org/writing/structure/)
---
**将学习**:
- OpenAI API 基础
- 第一个AI应用
- 与AI模型对话
**项目**: 连接OpenAI API,构建智能对话应用
**Phase 1 完成总结**:
- ✅ Day 1: Python基础(类、函数、IO)
- ✅ Day 2: 数据管理(JSON、文件操作)
- ✅ Day 3: API调用(requests、HTTP)
- ✅ Day 4: 数据分析(CSV、统计)
- ✅ Day 5: 错误处理(异常、日志)
- ✅ Day 6: OOP进阶(继承、序列化)
- ✅ Day 7: 综合项目(财务管理)
---
> "Day 7是Phase 1的收官之作,我把前6天学的所有知识都用上了:
> - 类设计(Transaction, Budget, FinanceTracker)
> - 字典操作(budgets, 分类统计)
> - JSON序列化(数据持久化)
> - 数据分析(defaultdict, 排序, 格式化)
> - 错误处理(金额验证)
> - 日期处理(月度/年度报表)
>
> 最大的感悟是:编程不是死记硬背语法,而是把各种工具组合起来解决问题。
> 这个项目让我理解了'架构设计'——如何把复杂功能拆分成多个类,每个类负责一块。
>
> 明天开始Phase 2,要学习AI和LangChain了,超级期待!"
---
**完整代码**: [`day07_finance_tracker.py`](https://github.com/duquanyong/python-ai-learning/blob/main/day07_finance_tracker.py)
**数据文件**: `finance_data.json`(运行后自动生成)
---
<div align="center">
<p>⭐ Phase 1 完成!恭喜!⭐</p>
<p><em>"7天的坚持,Python基础已牢。接下来,让AI为你所用!"</em></p>
</div>