Python:临时做个计数表,`collections.Counter` 比手写循环省点事

13 次浏览2 条回复

有时候只是想统计一串日志级别、标签或者状态码出现了几次,手写 dict 加一堆 if key not in 会有点啰嗦。标准库的 Counter 挺适合这种小活。

环境:Python 3.8+。保存成 counter-demo.py

from collections import Counter

levels = ['info', 'warn', 'info', 'error', 'warn', 'info']
counts = Counter(levels)

print(counts)
print(counts['info'])
print(counts.most_common(2))
print(counts['debug'])

跑一下:

python counter-demo.py

most_common(2) 会拿到出现最多的两个项。没出现过的 key 读出来是 0,这一点写临时统计脚本时还挺舒服。

不过它也只是计数工具,如果后面要按时间窗口、用户维度之类的复杂聚合,还是早点换成更清楚的数据结构比较好。

Counter 还有个小地方挺好用:两个计数结果可以直接做加减。比如分批读日志时,每批先各自 Counter,最后 total += part 就行。

不过减法会把 0 和负数结果丢掉,这个有时候容易误会;如果真要保留负数差值,可能普通 dict 或 subtract() 后再看原对象更清楚。

还有个容易被忽略的是 update() 可以直接喂迭代器,不一定要先自己拼列表。比如一行行读日志时可以边读边 counts.update([level]),最后再看 most_common()

但如果数据量特别大、key 又很多,还是要留意内存,Counter 不是流式聚合的银弹。