python-sortedcontainers:纯 Python 的有序集合,性能不输 C 扩展
grantjenks 维护的 python-sortedcontainers,目前收获了 3,949 个 Star:
Python 标准库已经相当完善,但当你真正需要一个有序列表、有序字典或有序集合时,选择就变得困难。市面上大部分实现依赖 C 扩展,文档和基准测试也不尽如人意。
python-sortedcontainers 提供了一个纯 Python 的替代方案,部署和使用都很简单,不需要安装 C 编译器,也不用处理预编译的自定义扩展。
这个库包含三种核心数据类型:SortedList、SortedDict 和 SortedSet。它们保持了元素的有序状态,API 设计贴近 Python 原生风格,上手几乎没有门槛。
>>> from sortedcontainers import SortedList
>>> sl = SortedList(['e', 'a', 'c', 'd', 'b'])
>>> sl
SortedList(['a', 'b', 'c', 'd', 'e'])
>>> sl *= 10_000_000
>>> sl.count('c')
10000000
>>> sl[-3:]
['e', 'e', 'e']
上述操作的时间复杂度均优于线性。当有序列表被放大到一千万倍时,每个元素只需保存一个对象指针,内存开销远低于传统二叉树实现。这种分片存储的方式规避了 O(N) 的插入开销,是它性能优异的关键。
SortedDict 和 SortedSet 的用法同样直接:
>>> from sortedcontainers import SortedDict
>>> sd = SortedDict({'c': -3, 'a': 1, 'b': 2})
>>> sd
SortedDict({'a': 1, 'b': 2, 'c': -3})
>>> sd.popitem(index=-1)
('c', -3)
>>> from sortedcontainers import SortedSet
>>> ss = SortedSet('abracadabra')
>>> ss
SortedSet(['a', 'b', 'c', 'd', 'r'])
>>> ss.bisect_left('c')
2
这个库被不少知名项目采用,包括量化交易库 Zipline、二进制分析平台 Angr、异步 I/O 库 Trio,以及分布式计算框架 Dask Distributed。Python 软件基金会 Fellow Alex Martelli 曾评价这个库的分片实现思路简单且有效。作者 Jeff Knupp 最初对 "fast as C-extensions" 这个说法持怀疑态度,直到亲自查看了性能对比数据才信服。
性能是 python-sortedcontainers 的一大卖点。它的运行速度经常能超过那些 C 语言实现的同类产品。完整的性能对比数据可以在项目文档的性能章节找到,涵盖了不同替代方案、运行时环境和负载因子的详细测试。
其他特性还包括:
- 纯 Python 实现,无需编译 C 扩展
- 功能丰富,比如可以直接获取有序字典中最大的五个键:d.keys()[-5:]
- 100% 单元测试覆盖,并经过长时间压力测试
- API 与旧版 blist 和 bintrees 模块高度兼容
- 支持 Python 3.7 到 3.12,以及 PyPy3
- 在 Linux、Mac OSX 和 Windows 上均有测试
安装
通过 pip 直接安装:
$ pip install sortedcontainers
基本用法
导入后即可在代码中使用,sortedcontainers 模块和各个类都内置了 help 文档:
>>> import sortedcontainers
>>> help(sortedcontainers)
>>> from sortedcontainers import SortedDict
>>> help(SortedDict)
>>> help(SortedDict.popitem)
项目文档包含用户指南、多维度性能对比、实现细节解析和完整的 API 参考,内容相当全面。作者在文档中详细解释了分片策略的工作原理,以及为什么这种方式在内存和速度上都能取得好结果。如果你正在寻找一个稳定可靠的有序集合方案,这个库值得纳入考虑。