专项练习 · 8 分钟阅读

Python collections 练习:计数、分组与队列

collections 模块提供一组减少样板代码的小工具。你不需要手写计数循环、缺失键判断或队列,而是直接选择行为已经匹配问题的容器。

先计数,再查询

Counter 把可迭代对象转换成计数。它是字典子类,所以缺失键读取为零,同时仍可使用普通映射方法。most_common 适合快速排序,直接索引适合单次查询。

from collections import Counter
votes = ["yes", "no", "yes", "yes"]
counts = Counter(votes)
print(counts["yes"])
print(counts.most_common(1))

一次计数,多次查询

给缺失键合理的默认值

defaultdict 在键不存在时调用工厂函数。使用 list 时可以直接 append,不必先判断键是否存在。工厂必须可调用,默认值只在访问该键时创建。

from collections import defaultdict
groups = defaultdict(list)
for word in ["ant", "ape", "bee"]:
    groups[word[0]].append(word)
print(dict(groups))

分组时不再判断键

两端都重要时用 deque

列表在右端操作高效,在左端操作代价较高。deque 支持在两端快速添加和弹出。队列可以用 appendleft 和 popleft,需要循环移动元素时可以用 rotate。

from collections import deque
queue = deque(["a", "b"])
queue.append("c")
queue.popleft()
print(list(queue))

两端操作都很快

把计数当作可运算的值

Counter 支持计数相加和相减。比较两组物品时很方便,但相减会丢弃非正数结果。update 可以从另一个可迭代对象或映射累加计数。

from collections import Counter
first = Counter("aab")
second = Counter("abb")
print(first + second)
print(first - second)

计数也能组合

按需要的操作选择容器

根据最常执行的操作选择容器:计数、分组还是两端访问。如果既不需要默认值也不需要计数,普通 dict 仍然最合适。可读性来自工具与任务匹配,而不是在一个文件里用遍所有容器。

from collections import Counter, deque
print(Counter("aba").most_common(1))
print(deque([1, 2, 3]).popleft())

让容器匹配任务

你的练习清单

常见问题

Counter 是字典吗?

是。Counter 是 dict 的子类,查询缺失键时按零处理。

什么时候用 defaultdict 而不是 dict.get?

当同一个缺失键默认值在循环中反复出现时用 defaultdict。只查一两次时,dict.get 通常更清楚。

deque 可以索引吗?

可以,但索引不是使用 deque 的主要理由。两端频繁增删才是它最合适的场景。

练习 collections

12 道题,覆盖 Counter、defaultdict、deque、分组和容器选择。

打开练习

继续阅读: