`collections` 是 Python 标准库中一个非常强大且常用的模块,它提供了许多**高性能、开箱即用的容器数据类型**,扩展了内置的 `list`、`dict`、`set`、`tuple` 等基础类型的功能。
---
## 📚 一、`collections` 模块的核心类
| 类名 | 用途 |
|------|------|
| `defaultdict` | 带默认值的字典,避免 KeyError |
| `Counter` | 计数器,统计元素出现次数 |
| `deque` | 双端队列,支持高效头尾操作 |
| `namedtuple` | 命名元组,带字段名的不可变结构 |
| `OrderedDict` | 有序字典,保持插入顺序(Python < 3.7) |
| `ChainMap` | 多个字典的逻辑合并 |
| `UserDict` / `UserList` / `UserString` | 可继承的基础容器类 |
下面我们逐一详解,并附上实用代码示例。
---
## 1. `defaultdict` —— 自动初始化的字典 ✅
### 🔍 作用
当访问不存在的 key 时,自动创建一个默认类型的 value。
### 💡 场景
- 构建 `dict[int, list]`、`dict[str, set]` 等嵌套结构
- 避免写 `if key not in d: d[key] = []`
### ✅ 示例
```python
from collections import defaultdict
# 创建一个 value 为列表的字典
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(3)
print(d) # defaultdict(<class 'list'>, {'a': [1, 2], 'b': [3]})
# 统计字符频次
freq = defaultdict(int)
for c in "hello":
freq[c] += 1
print(freq) # {'h': 1, 'e': 1, 'l': 2, 'o': 1}
```
> ⚠️ 注意:`defaultdict` 不会为未访问的 key 创建条目,只有当你“读取”某个 key 时才生成。
---
## 2. `Counter` —— 计数神器 🔢
### 🔍 作用
统计可哈希对象的出现次数。
### ✅ 示例
```python
from collections import Counter
# 统计字符
c = Counter("hello")
print(c) # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})
# 统计单词
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
c = Counter(words)
print(c.most_common(2)) # [('apple', 3), ('banana', 2)]
# 支持加减运算
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
print(c1 + c2) # Counter({'a': 4, 'b': 3})
print(c1 - c2) # Counter({'a': 2})
```
### 🧩 实用技巧
```python
# 找出两个字符串是否是字母异位词(anagram)
def is_anagram(s1, s2):
return Counter(s1) == Counter(s2)
print(is_anagram("listen", "silent")) # True
```
---
## 3. `deque` —— 双端队列 🔄
### 🔍 作用
在列表两端进行 **O(1)** 时间复杂度的添加/删除操作。
### 💡 对比 `list`
| 操作 | `list` | `deque` |
|------|--------|--------|
| `append()` | O(1) amortized | O(1) |
| `appendleft()` | ❌ 无 | O(1) ✅ |
| `pop(0)` 或 `pop_left()` | O(n) | O(1) ✅ |
| `insert(0, x)` | O(n) | O(1) for `appendleft` |
### ✅ 示例
```python
from collections import deque
dq = deque([1, 2, 3])
dq.appendleft(0)
dq.append(4)
dq.popleft()
print(dq) # deque([1, 2, 3, 4])
# 限制长度(滑动窗口)
fixed_dq = deque(maxlen=3)
for i in range(5):
fixed_dq.append(i)
print(fixed_dq) # deque([2, 3, 4], maxlen=3)
```
### 🧩 应用场景
- BFS 层序遍历
- 滑动窗口最大值
- 实现缓冲区、历史记录等
---
## 4. `namedtuple` —— 命名元组 🏷️
### 🔍 作用
创建轻量级、不可变的类式结构,但比 class 更快更省内存。
### ✅ 示例
```python
from collections import namedtuple
# 定义一种“点”类型
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y) # 10 20
print(p) # Point(x=10, y=20)
print(p._asdict()) # OrderedDict([('x', 10), ('y', 20)])
# 定义一个数据包结构
Packet = namedtuple('Packet', ['source', 'destination', 'timestamp'])
pkt = Packet(source=1, destination=2, timestamp=100)
print(pkt.destination) # 2
```
> ✅ 优势:可读性强、支持索引和属性访问、线程安全、序列化方便
---
## 5. `OrderedDict` —— 有序字典 📜
### 🔍 作用
保持键值对的插入顺序。
> ⚠️ Python 3.7+ 中普通 `dict` 已经默认保持插入顺序,所以 `OrderedDict` 使用减少。
### ✅ 特有功能
```python
from collections import OrderedDict
od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3
od.move_to_end('a') # 移到最后
print(od) # OrderedDict([('b', 2), ('c', 3), ('a', 1)])
# 比较时考虑顺序
od1 = OrderedDict([('a', 1), ('b', 2)])
od2 = OrderedDict([('b', 2), ('a', 1)])
print(od1 == od2) # False(普通 dict 相等)
```
---
## 6. `ChainMap` —— 多字典视图 🔗
### 🔍 作用
将多个字典组合成一个逻辑上的整体,查找时逐个搜索。
### ✅ 示例
```python
from collections import ChainMap
default_config = {'host': 'localhost', 'port': 8080}
user_config = {'port': 9000}
combined = ChainMap(user_config, default_config)
print(combined['host']) # localhost(从 default_config 获取)
print(combined['port']) # 9000(优先 user_config)
```
### 🧩 应用场景
- 配置管理(用户配置覆盖默认配置)
- 变量作用域链(如局部变量 → 全局变量)
---
## 7. `UserDict`, `UserList`, `UserString` —— 可继承容器 🛠️
当你想自定义容器行为时使用。
### ✅ 示例:带长度限制的字典
```python
from collections import UserDict
class LimitedDict(UserDict):
def __init__(self, max_len=5):
super().__init__()
self.max_len = max_len
def __setitem__(self, key, value):
if len(self.data) >= self.max_len:
# 删除最老的一项(基于插入顺序)
old_key = next(iter(self.data))
del self.data[old_key]
super().__setitem__(key, value)
d = LimitedDict(max_len=3)
for i in range(5):
d[f'key{i}'] = i
print(d) # {'key2': 2, 'key3': 3, 'key4': 4}
```
---
## 🎯 总结:各类型适用场景一览
| 类型 | 推荐使用场景 |
|------|-------------|
| `defaultdict` | 构建分组映射、邻接表、频率统计 |
| `Counter` | 统计频次、比较集合、找众数 |
| `deque` | 高频头尾操作、BFS、滑动窗口 |
| `namedtuple` | 表示简单数据结构(如坐标、记录) |
| `OrderedDict` | 需要精确控制顺序或做 LRU 缓存 |
| `ChainMap` | 多层配置合并、作用域链 |
| `UserDict/List` | 自定义容器逻辑 |
---
## 🧪 小练习:综合应用
用 `collections` 实现一个简单的**包路由器统计器**:
```python
from collections import defaultdict, Counter, deque
class SimpleRouter:
def __init__(self):
self.packets = deque()
self.by_dest = defaultdict(list)
self.src_count = Counter()
def add_packet(self, src, dest, ts):
packet = (src, dest, ts)
self.packets.append(packet)
self.by_dest[dest].append(ts)
self.src_count[src] += 1
def get_recent_dest_packets(self, dest, last_n=5):
return self.by_dest[dest][-last_n:]
def top_sources(self, n=3):
return self.src_count.most_common(n)
# 使用示例
r = SimpleRouter()
r.add_packet(1, 2, 100)
r.add_packet(1, 3, 101)
r.add_packet(2, 2, 102)
r.add_packet(3, 2, 103)
print(r.get_recent_dest_packets(2)) # [100, 102, 103]
print(r.top_sources()) # [(1, 2), (2, 1), (3, 1)]
```
---