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。
- 用 defaultdict(list) 分组,避免预先创建列表。
- 队列和左端高频操作使用 deque。
- 记住 Counter 相减会丢弃非正计数。
- 根据最常重复的操作选择容器。
常见问题
Counter 是字典吗?
是。Counter 是 dict 的子类,查询缺失键时按零处理。
什么时候用 defaultdict 而不是 dict.get?
当同一个缺失键默认值在循环中反复出现时用 defaultdict。只查一两次时,dict.get 通常更清楚。
deque 可以索引吗?
可以,但索引不是使用 deque 的主要理由。两端频繁增删才是它最合适的场景。
练习 collections
12 道题,覆盖 Counter、defaultdict、deque、分组和容器选择。
继续阅读: