Maya 想知道最好卖的饮料、正在排队的订单,还有按杯型统计的数量。三个循环也能做,三个容器做得更清楚。哪个容器不用 dict.get 就能计数?
collections 模块为常见任务提供专用容器:计数、按键分组,以及在两端添加或删除元素。它们各自只解决一个小问题,却能让代码意图更清楚。 你还会保留固定长度的窗口、叠加配置,并比较库存。
用 Counter 计数
Counter 是字典的子类,用来统计出现次数。访问不存在的键会返回零,而不是抛出 KeyError。most_common 会把次数最高的项排在前面,适合做汇总和排行。
from collections import Counter
votes = ["tea", "coffee", "tea"]
counts = Counter(votes)
print(counts["tea"])
print(counts.most_common(1))先计数,再排序
用 defaultdict 分组
访问不存在的键时,defaultdict 会调用工厂函数。把 list 作为工厂,每个新键都会从空列表开始。这样就不必在追加前反复检查键是否存在。
from collections import defaultdict
groups = defaultdict(list)
for name, team in [("Ada", "A"), ("Grace", "B"), ("Lin", "A")]:
groups[team].append(name)
print(dict(groups))每个新键都有一个列表
用 deque 操作两端
deque 支持在两端高效添加和删除。popleft 从队首移除最早的元素,append 从队尾加入。它很适合队列和滑动窗口。
from collections import deque
queue = deque(["a", "b"])
queue.append("c")
queue.popleft()
print(list(queue))双端队列
保留固定长度的滚动窗口
带 maxlen 的 deque 会自动丢掉最旧的元素,很适合移动平均或短活动流:不用切片复制,也不用维护索引。窗口大小在创建 deque 时就固定下来。
from collections import deque
window = deque(maxlen=3)
for reading in [10, 12, 11, 15]:
window.append(reading)
print(list(window), round(sum(window) / len(window), 1))新值进来,旧值自动离开
用 ChainMap 叠加配置
ChainMap 从左到右查找各个映射。把用户设置放前面、默认值放后面,用户没有设置的键会自动落到默认层,不需要复制合并整本字典。new_child() 可以为一个请求或一个页面创建临时覆盖层。
from collections import ChainMap
defaults = {"theme": "light", "page_size": 20}
user = {"theme": "dark"}
settings = ChainMap(user, defaults)
print(settings["theme"], settings["page_size"])
print("page_size" in user)
scoped = settings.new_child({"page_size": 50})
print(scoped["page_size"], settings["page_size"])不复制字典也能覆盖
Counter 运算只保留正库存
两个 Counter 相减时,零和负数会被丢掉。用来算剩余库存很方便,但结果不再是完整账本。交集 & 对每个键保留较小的计数,回答的是另一个问题:两份库存有多少共同部分?
from collections import Counter
stock = Counter({"tea": 3, "latte": 2})
sold = Counter({"tea": 2, "latte": 2, "mocha": 1})
left = stock - sold
print(left)
print(list(left.elements()))
print(stock & sold)剩余库存和共同库存不是一回事
本课要点
- Counter 统计可哈希值,缺失键返回零。
- most_common 按次数从高到低排序。
- defaultdict 会为缺失键创建默认值。
- deque 支持高效的两端操作。
- 离开局部代码时,可以把专用容器转换成普通列表或字典。
- 滚动窗口用 maxlen,配置优先级用 ChainMap,库存视图用 Counter 运算。
常见错误
- 键可能不存在时,仍然对普通字典使用 counts[key]。
- 忘记 defaultdict 在读取时也会插入键。
- 需要队列时反复使用 list.pop(0),而没有考虑 deque。
- 把 Counter 相减当成完整审计记录:零和负数结果会消失。
用 Counter 统计 ['a', 'b', 'a'],再往 defaultdict(list) 里添加一个新团队。
动手试试
改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。
练习本课
12 道题,作答后立即看到解释。