Counter是Python中统计元素频率最直接高效的方式,继承自dict,支持自动初始化、most_common()、+/-运算等,性能优于手动dict循环,且对任意可哈希对象通用。

collections.Counter 是 Python 中统计列表元素频率最直接、最高效的方式,无需手写循环或字典计数逻辑,且支持开箱即用的常见操作(如取最高频、批量更新)。
为什么不用 dict 循环手动计数?
手动用 dict 统计需要处理键不存在时的初始化(比如用 get() 或 setdefault()),代码冗长且易错;而 Counter 内部已优化哈希与计数路径,在 C 层实现关键逻辑,实测对万级以内列表,性能比纯 Python 循环快 2–3 倍。
- 常见错误:用
{}+for遍历时漏判KeyError,导致程序中断 - 更隐蔽的问题:频繁调用
dict.get(k, 0) + 1会重复查哈希表,Counter在单次构造中批量完成所有键的插入与累加 - 兼容性注意:
Counter继承自dict,所有dict方法都可用,但其键值对顺序在 Python 3.7+ 才保证插入序(此前是散列序)
Counter 的三种常用初始化方式
根据数据来源灵活选择构造方法,避免多余转换:
- 直接传入可迭代对象:
Counter([1, 2, 2, 3, 3, 3])→Counter({3: 3, 2: 2, 1: 1}) - 传入字典(用于已有频次映射):
Counter({'a': 2, 'b': 1}) - 用关键字参数(适合少量已知项):
Counter(a=2, b=1)—— 注意键必须是合法标识符
⚠️ 容易踩的坑:Counter("abcc") 会按字符计数,不是按字符串整体;若想统计字符串列表中每个字符串出现次数,确保传入的是 list 而非字符串本身。
立即学习“Python免费学习笔记(深入)”;
高频操作:取 top-N、合并、减法与缺失键处理
Counter 提供了语义清晰的实用方法,比手写 sorted(..., key=lambda...) 更简洁安全:
- 取前 N 高频:
c.most_common(3)返回[('x', 5), ('y', 4), ('z', 2)]形式的列表;传None则返回全部,按频次降序 - 合并两个计数器:
c1 + c2(对应键值相加),c1 - c2(只保留结果 > 0 的键,负值被丢弃) - 访问不存在的键不报错:
c['missing_key']返回0(这是Counter对__missing__的重写,普通dict会抛KeyError) - 重置为零:
c.clear(),或直接c = Counter()
性能提示:most_common(n) 时间复杂度是 O(n + k log n)(k 为不同元素数),当只要前几项时,远优于先 sorted(c.items(), ...) 全排序。
和 numpy.unique 或 pandas.Series.value_counts() 怎么选?
如果已在用科学计算栈,需权衡上下文依赖与数据形态:
- 纯 Python 列表/元组/字符串 → 无条件选
Counter:无额外依赖、内存占用低、API 直观 - 数值型数组且已引入
numpy→np.unique(arr, return_counts=True)更快(C 实现 + 缓存友好),但返回的是两个平行数组,不如Counter的字典接口自然 - 数据已在
DataFrame或需分组统计 →Series.value_counts()自带归一化、排序、空值处理等选项,但启动开销大,小数据反而慢
一个常被忽略的细节:Counter 对任意可哈希对象都有效(包括 tuple、frozenset),而 numpy.unique 要求元素类型统一且支持向量化比较——比如统计含混合类型的列表,只有 Counter 能稳住。


















