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

5.8 KiB

doc_type, full_text
doc_type full_text
short sources/05_Collections.md

05_Collections 总结

本文介绍 Python 标准库 collections 模块中几个常用的数据处理工具,重点包括 Counter、defaultdict 和 deque,展示它们如何简化计数、分组索引和保留有限历史记录等任务。相关主题可延伸为 Python标准库、concepts/数据计数与汇总、字典与映射、序列与队列。

核心主题

collections 模块提供了多种专门的数据结构,适合处理常见但用普通 dict、list 实现会显得繁琐的数据管理问题。

本文重点场景包括:

  • 统计每只股票的总持仓数量
  • 将一个键映射到多个值
  • 保存最近 N 条历史记录

使用 Counter 进行计数与汇总

当需要统计某类对象的累计数量时,可以使用 collections.Counter。

示例数据中,同一只股票可能出现多次:

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,然后逐项累加:

from collections import Counter

total_shares = Counter()
for name, shares, price in portfolio:
    total_shares[name] += shares

这样,重复出现的股票名会被合并到同一个计数项中。例如:

total_shares['IBM']

结果为:

150

这说明 IBM 的两条记录被汇总为总股数 150。

Counter 的字典行为与排序功能

Counter 可以像普通字典一样通过键访问值:

holdings['IBM']
holdings['MSFT']

同时,它还提供了计数对象常用的额外方法。例如,可以使用 most_common() 获取持仓数量最多的股票:

holdings.most_common(3)

返回结果类似:

[('MSFT', 250), ('IBM', 150), ('CAT', 150)]

这使得 Counter 不仅适合做统计,也适合做排名和频率分析。

合并多个 Counter

Counter 支持直接相加,这对合并多个数据源中的统计结果非常方便。

例如有两个投资组合:

combined = holdings + holdings2

合并后,相同股票的股数会自动相加:

Counter({'MSFT': 275, 'HPQ': 250, 'GE': 220, 'AA': 150, 'IBM': 150, 'CAT': 150})

这体现了 Counter 在数据汇总、聚合和表格化统计中的优势。

使用 defaultdict 处理一对多映射

当一个键需要关联多个值时,普通字典需要手动检查键是否存在,而 defaultdict 可以自动为新键创建默认值。

示例:将股票名称映射到该股票的所有交易记录:

from collections import defaultdict

holdings = defaultdict(list)
for name, shares, price in portfolio:
    holdings[name].append((shares, price))

访问 IBM 时会得到它对应的多条记录:

holdings['IBM']

结果:

[(50, 91.1), (100, 45.23)]

defaultdict(list) 的作用是:当访问一个不存在的键时,自动创建一个空列表作为默认值,因此可以直接调用 .append()。

这类模式常用于:

  • 分组数据
  • 建立索引
  • 一对多映射
  • 按类别聚合记录

相关概念可连接到 字典与映射 和 数据分组。

使用 deque 保存有限历史记录

如果需要保存最近 N 个元素,可以使用 collections.deque。

示例:保存文件处理中最近 N 行内容:

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,加载股票投资组合数据:

python3 -i report.py

然后使用 read_portfolio('Data/portfolio.csv') 读取投资组合,并通过 Counter 汇总每只股票的持仓总数:

from collections import Counter

holdings = Counter()
for s in portfolio:
    holdings[s['name']] += s['shares']

结果示例:

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 数据结构和标准库学习的重要部分。