collections
collections 提供了比列表、元组和普通字典更适合特定场景的容器。常用类型有 Counter、defaultdict、deque、namedtuple 和 OrderedDict。
Counter:计数器
Counter 接收可迭代对象或映射,统计每个元素出现次数:
from collections import Counter
counts = Counter("banana")
print(counts) # Counter({'a': 3, 'n': 2, 'b': 1})
print(counts["a"], counts["x"]) # 3 0(不存在的键返回 0)
print(counts.most_common(2)) # [('a', 3), ('n', 2)]
update() 增加计数,subtract() 减少计数;它们接收的是元素而不是“替换字典”。elements() 返回按计数重复的元素,零或负数计数不会产生元素。
left = Counter(a=3, b=1)
right = Counter(a=1, b=2)
print(left + right) # Counter({'a': 4, 'b': 3})
print(left - right) # Counter({'a': 2}),只保留正数
print(left & right) # 交集取较小计数
print(left | right) # 并集取较大计数
defaultdict:自动提供默认值
当访问不存在的键时,defaultdict 调用工厂函数创建默认值,适合分组和聚合:
from collections import defaultdict
groups = defaultdict(list)
for name, team in [("小林", "A"), ("小周", "B"), ("小陈", "A")]:
groups[team].append(name)
print(dict(groups)) # {'A': ['小林', '小陈'], 'B': ['小周']}
工厂可以是 int、set 或自定义函数。注意,groups["C"] 会改变字典;只检查是否存在时使用 "C" in groups 或 groups.get("C")。
deque:双端队列
deque 在两端追加和弹出都是 O(1),适合队列、栈和滑动窗口:
from collections import deque
queue = deque([1, 2])
queue.append(3)
queue.appendleft(0)
print(queue.popleft()) # 0
print(queue.pop()) # 3
recent = deque(maxlen=3)
for value in [10, 20, 30, 40]:
recent.append(value)
print(recent) # deque([20, 30, 40])
rotate(n) 可循环移动元素,extendleft() 会反向加入可迭代对象。随机索引访问中间元素不如列表高效。
namedtuple 与其他类型
namedtuple 创建轻量、不可变的元组子类,字段可用名称访问:
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x, p.y, p._asdict())
新项目通常优先使用 dataclasses.dataclass,因为它支持默认值、类型注解和可变对象。OrderedDict 在现代 Python 中很少需要,普通 dict 已保证插入顺序;但 move_to_end() 和顺序敏感的相等比较仍是它的特色。
选择建议
| 需求 | 推荐类型 |
|---|---|
| 统计频次、取 Top N | Counter |
| 按键分组并自动初始化 | defaultdict |
| 两端进出、限长历史 | deque |
| 不可变记录对象 | namedtuple |
| 需要移动键或顺序比较 | OrderedDict |