Files
coding-mentor-agent/kb/python-course-kb-practical-python/wiki/summaries/05_Collections.md
T

218 lines
5.8 KiB
Markdown

---
doc_type: short
full_text: sources/05_Collections.md
---
# 05_Collections 总结
本文介绍 Python 标准库 `collections` 模块中几个常用的数据处理工具,重点包括 `Counter`、`defaultdict` 和 `deque`,展示它们如何简化计数、分组索引和保留有限历史记录等任务。相关主题可延伸为 Python标准库、[[concepts/数据计数与汇总]]、字典与映射、序列与队列。
## 核心主题
`collections` 模块提供了多种专门的数据结构,适合处理常见但用普通 `dict`、`list` 实现会显得繁琐的数据管理问题。
本文重点场景包括:
- 统计每只股票的总持仓数量
- 将一个键映射到多个值
- 保存最近 N 条历史记录
## 使用 `Counter` 进行计数与汇总
当需要统计某类对象的累计数量时,可以使用 `collections.Counter`。
示例数据中,同一只股票可能出现多次:
```python
portfolio = [
('GOOG', 100, 490.1),
('IBM', 50, 91.1),
('CAT', 150, 83.44),
('IBM', 100, 45.23),
('GOOG', 75, 572.45),
('AA', 50, 23.15)
]
```
如果希望计算每只股票的总股数,可以创建一个空的 `Counter`,然后逐项累加:
```python
from collections import Counter
total_shares = Counter()
for name, shares, price in portfolio:
total_shares[name] += shares
```
这样,重复出现的股票名会被合并到同一个计数项中。例如:
```python
total_shares['IBM']
```
结果为:
```python
150
```
这说明 `IBM` 的两条记录被汇总为总股数 150。
## `Counter` 的字典行为与排序功能
`Counter` 可以像普通字典一样通过键访问值:
```python
holdings['IBM']
holdings['MSFT']
```
同时,它还提供了计数对象常用的额外方法。例如,可以使用 `most_common()` 获取持仓数量最多的股票:
```python
holdings.most_common(3)
```
返回结果类似:
```python
[('MSFT', 250), ('IBM', 150), ('CAT', 150)]
```
这使得 `Counter` 不仅适合做统计,也适合做排名和频率分析。
## 合并多个 `Counter`
`Counter` 支持直接相加,这对合并多个数据源中的统计结果非常方便。
例如有两个投资组合:
```python
combined = holdings + holdings2
```
合并后,相同股票的股数会自动相加:
```python
Counter({'MSFT': 275, 'HPQ': 250, 'GE': 220, 'AA': 150, 'IBM': 150, 'CAT': 150})
```
这体现了 `Counter` 在数据汇总、聚合和表格化统计中的优势。
## 使用 `defaultdict` 处理一对多映射
当一个键需要关联多个值时,普通字典需要手动检查键是否存在,而 `defaultdict` 可以自动为新键创建默认值。
示例:将股票名称映射到该股票的所有交易记录:
```python
from collections import defaultdict
holdings = defaultdict(list)
for name, shares, price in portfolio:
holdings[name].append((shares, price))
```
访问 `IBM` 时会得到它对应的多条记录:
```python
holdings['IBM']
```
结果:
```python
[(50, 91.1), (100, 45.23)]
```
`defaultdict(list)` 的作用是:当访问一个不存在的键时,自动创建一个空列表作为默认值,因此可以直接调用 `.append()`。
这类模式常用于:
- 分组数据
- 建立索引
- 一对多映射
- 按类别聚合记录
相关概念可连接到 字典与映射 和 数据分组。
## 使用 `deque` 保存有限历史记录
如果需要保存最近 N 个元素,可以使用 `collections.deque`。
示例:保存文件处理中最近 N 行内容:
```python
from collections import deque
history = deque(maxlen=N)
with open(filename) as f:
for line in f:
history.append(line)
...
```
当设置 `maxlen=N` 后,`deque` 会自动维持固定长度。新元素加入时,如果超过最大长度,最旧的元素会被自动丢弃。
这适合用于:
- 最近历史记录
- 滑动窗口
- 日志尾部追踪
- 流式数据处理
相关主题可扩展为 序列与队列、滑动窗口。
## 练习 2.18:使用 `Counter` 表格化统计
练习要求在交互模式中运行 `report.py`,加载股票投资组合数据:
```bash
python3 -i report.py
```
然后使用 `read_portfolio('Data/portfolio.csv')` 读取投资组合,并通过 `Counter` 汇总每只股票的持仓总数:
```python
from collections import Counter
holdings = Counter()
for s in portfolio:
holdings[s['name']] += s['shares']
```
结果示例:
```python
Counter({'MSFT': 250, 'IBM': 150, 'CAT': 150, 'AA': 100, 'GE': 95})
```
该练习强调:当原始数据中同一股票有多条记录时,`Counter` 可以自然地将这些记录合并为单个统计项。
随后练习又读取第二个投资组合 `portfolio2.csv`,创建另一个 `Counter`,并用加法合并两个统计结果。
## 关键收获
- `collections` 是 Python 中非常实用的标准库模块,适合处理专门的数据管理问题。
- `Counter` 用于计数、汇总、排名和合并统计结果。
- `defaultdict` 用于简化默认值处理,尤其适合一对多映射和分组。
- `deque` 适合保存固定长度的历史记录或实现队列类数据结构。
- 遇到表格化统计、索引构建、分组聚合等问题时,应优先考虑 `collections` 模块。
## 延伸阅读方向
本文最后指出,`collections` 模块内容丰富,值得后续深入学习。除了本文介绍的 `Counter`、`defaultdict` 和 `deque`,该模块还包含其他有用工具,可作为 Python 数据结构和标准库学习的重要部分。
## Related Concepts
- [[concepts/队列与滑动窗口]]
- [[concepts/Python-容器]]
- [[concepts/字典与数据建模]]
- [[concepts/列表与序列]]
- [[concepts/模块与-import]]
- [[concepts/元组与解包]]
- [[concepts/Python-交互式解释器]]
- [[concepts/文件读写]]
- [[concepts/上下文管理器]]
- [[concepts/迭代协议与生成器]]
- [[concepts/CSV-数据处理]]