记录:Python `collections` 模块 API
·
Python `collections` 模块 API
Python collections 模块 API
本指南旨在提供
collections模块中所有核心容器的完整 API 参考。每个类都将包含一个详尽的表格,列出其所有公开的方法和属性,随后是展示其功能的代码示例。
一、 计数器 (Counter)
Counter 是 dict 的子类,专门用于对可哈希对象进行计数。
Counter 完整 API
| 方法 / 属性 / 运算 | 描述 | 时间复杂度 |
|---|---|---|
Counter([iterable-or-mapping]) | 构造函数。可以用可迭代对象、映射(字典)或关键字参数初始化。 | O(N) |
elements() | 返回一个迭代器,其中每个元素重复出现的次数等于其计数值。忽略计数值小于 1 的元素。 | O(sum(counts)) |
most_common([n]) | 返回一个列表,包含 n 个最常见的 (元素, 计数值) 对,按计数值从高到低排序。如果 n 省略,则返回所有元素。 | O(M log M) (M是唯一元素数) |
subtract([iterable-or-mapping]) | 从一个可迭代对象或映射中减去元素的计数值。这是一个原地操作。 | O(N) |
update([iterable-or-mapping]) | (重写 dict 方法) 从一个可迭代对象或映射中加上元素的计数值,而不是替换。这是一个原地操作。 | O(N) |
c1 + c2 | (数学运算) 返回两个计数器的和(计数值相加)。 | O(M1 + M2) |
c1 - c2 | (数学运算) 返回两个计数器的差(计数值相减,只保留正数结果)。 | O(M1 + M2) |
c1 & c2 | (数学运算) 返回两个计数器的交集(取计数值的最小值)。 | O(M1 + M2) |
| **`c1 | c2`** | (数学运算) 返回两个计数器的并集(取计数值的最大值)。 |
+c / -c | (一元运算) +c 移除所有非正数计数的元素。-c 移除所有正数计数的元素并取绝对值。 | O(M) |
继承自 dict 的方法 | keys(), values(), items(), get(), pop(), popitem(), clear(), copy(), setdefault(), __contains__() 等所有标准字典方法。 | 同 dict |
| 未实现的方法 | fromkeys(iterable) | - |
Counter 代码示例
from collections import Counter
# 1. 初始化
c = Counter('gallahad')
print(f"初始计数器: {c}")
# 输出: 初始计数器: Counter({'a': 3, 'l': 2, 'g': 1, 'h': 1, 'd': 1})
# 2. most_common() 和 elements()
print(f"最常见的2个元素: {c.most_common(2)}")
# 输出: 最常见的2个元素: [('a', 3), ('l', 2)]
print(f"展开所有元素: {''.join(sorted(c.elements()))}")
# 输出: 展开所有元素: aaadghll
# 3. update() 和 subtract()
print(f"\n原始库存: {c}")
c.update('al') # 增加 'a' 和 'l' 的计数
print(f"update('al') 后: {c}")
# 输出: update('al') 后: Counter({'a': 4, 'l': 3, 'g': 1, 'h': 1, 'd': 1})
c.subtract('gall') # 减去 'g', 'a', 'l', 'l' 的计数
print(f"subtract('gall') 后: {c}")
# 输出: subtract('gall') 后: Counter({'a': 3, 'l': 1, 'g': 0, 'h': 1, 'd': 1})
# 4. 数学运算
c1 = Counter(a=4, b=2, c=0, d=-2)
c2 = Counter(a=1, b=2, c=3, d=4)
print(f"\nc1 = {c1}")
print(f"c2 = {c2}")
print(f"c1 + c2 (相加): {c1 + c2}")
print(f"c1 - c2 (相减,保留正数): {c1 - c2}")
print(f"c1 & c2 (交集 - min): {c1 & c2}")
print(f"c1 | c2 (并集 - max): {c1 | c2}")```
---
## 二、 双向队列 (`deque`)
一个在两端插入和删除都非常高效 (O(1)) 的列表式容器。
### `deque` 完整 API
| 方法 / 属性 | 描述 | 时间复杂度 |
| :--- | :--- | :--- |
| **`deque([iterable[, maxlen]])`** | 构造函数。`maxlen` 是可选参数,用于创建定长队列。 | `O(N)` |
| **`append(x)`** | 在队列右端添加元素 `x`。 | `O(1)` |
| **`appendleft(x)`** | 在队列左端添加元素 `x`。 | `O(1)` |
| **`pop()`** | 移除并返回队列右端的元素。 | `O(1)` |
| **`popleft()`** | 移除并返回队列左端的元素。 | `O(1)` |
| **`clear()`** | 移除所有元素,使队列长度为 0。 | `O(1)` |
| **`copy()`** | 创建队列的一个浅拷贝。 | `O(N)` |
| **`count(x)`** | 计算队列中等于 `x` 的元素数量。 | `O(N)` |
| **`extend(iterable)`** | 在队列右端添加 `iterable` 中的所有元素。 | `O(k)` (k是iterable长度) |
| **`extendleft(iterable)`** | 在队列左端添加 `iterable` 中的所有元素(注意:`iterable` 中的元素会**反序**添加)。 | `O(k)` |
| **`index(x[, start[, stop]])`** | 返回 `x` 在队列中第一次出现的位置。 | `O(N)` |
| **`insert(i, x)`** | 在位置 `i` 插入元素 `x`。 | `O(N)` |
| **`remove(value)`** | 移除第一个出现的 `value`。 | `O(N)` |
| **`reverse()`** | **原地**反转队列中的元素。 | `O(N)` |
| **`rotate(n=1)`** | 循环移动队列 `n` 步。`n` 为正数向右移,负数向左移。 | `O(k)` (k是n的绝对值) |
| **`maxlen`** (只读属性) | 返回队列的最大长度限制,如果无限制则为 `None`。 | `O(1)` |
### `deque` 代码示例
```python
from collections import deque
# 1. 基础操作 (append, pop)
d = deque('ghi')
d.append('j') # -> deque(['g', 'h', 'i', 'j'])
d.appendleft('f') # -> deque(['f', 'g', 'h', 'i', 'j'])
print(f"基础操作后: {d}")
right_val = d.pop() # -> 'j'
left_val = d.popleft() # -> 'f'
print(f"pop/popleft后: {d}, 弹出的值为: {left_val}, {right_val}")
# 2. extend 和 extendleft
d.extend('jkl') # -> deque(['g', 'h', 'i', 'j', 'k', 'l'])
print(f"extend后: {d}")
d.extendleft('fed') # -> deque(['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'])
print(f"extendleft后(注意反序): {d}")
# 3. rotate
d = deque('12345')
d.rotate(2)
print(f"\n向右 rotate(2): {d}") # 输出: deque(['4', '5', '1', '2', '3'])
d.rotate(-3)
print(f"向左 rotate(-3): {d}") # 输出: deque(['2', '3', '4', '5', '1'])
# 4. maxlen - 创建一个只保留最近5个元素的历史记录
history = deque(maxlen=5)
for i in range(10):
history.append(f"操作-{i}")
print(f"\n有 maxlen 的队列: {history}")
# 输出: deque(['操作-5', '操作-6', '操作-7', '操作-8', '操作-9'], maxlen=5)
三、 可命名元组 (namedtuple)
namedtuple 是一个工厂函数,用于创建带有字段名的 tuple 子类。
namedtuple 完整 API
| API | 类型 | 描述 |
|---|---|---|
namedtuple(typename, field_names, *, ...) | 工厂函数 | 创建一个新的 namedtuple 子类。 |
rename=False | 函数参数 | 如果为 True,无效的字段名(如关键字、重复名)会被自动重命名(如 _1)。 |
defaults=None | 函数参数 | 提供一个可迭代对象作为字段的默认值,从右至左应用。 |
module=None | 函数参数 | 设置所创建类的 __module__ 属性。 |
_fields | 实例属性 | 返回包含所有字段名的元组。 |
_field_defaults | 实例属性 | 返回一个将字段名映射到其默认值的字典。 |
_make(iterable) | 类方法 | 从一个可迭代对象创建一个新的实例。 |
_asdict() | 实例方法 | 返回一个 OrderedDict,将字段名映射到对应的值。 |
_replace(**kwargs) | 实例方法 | 返回一个新的实例,并用 kwargs 中的值替换指定的字段值。 |
继承自 tuple 的方法 | count(), index(), __getitem__ (索引), __len__, __iter__ 等所有标准元组方法。 |
namedtuple 代码示例
from collections import namedtuple
# 1. 定义与实例化 (带默认值)
# 为 'zipcode' 和 'country' 提供默认值
Address = namedtuple('Address', ['street', 'city', 'zipcode', 'country'], defaults=['', 'USA'])
home = Address('123 Main St', 'Anytown')
work = Address('456 High St', 'Otherville', '98765')
print(f"家庭地址: {home}")
# 输出: 家庭地址: Address(street='123 Main St', city='Anytown', zipcode='', country='USA')
# 2. 访问字段
print(f"工作地址的城市: {work.city} (邮编: {work.zipcode})")
# 3. _fields 和 _field_defaults 属性
print(f"\n所有字段: {Address._fields}")
print(f"字段默认值: {Address._field_defaults}")
# 4. _asdict() 和 _replace()
home_dict = home._asdict()
print(f"\n转换为字典: {home_dict}")
# 输出: 转换为字典: OrderedDict([('street', '123 Main St'), ('city', 'Anytown'), ...])
# _replace 创建一个新对象,原对象不变
new_home = home._replace(zipcode='12345')
print(f"更新邮编后的新地址: {new_home}")
print(f"原始地址不变: {home}")
四、 默认字典 (defaultdict)
dict 的子类,当访问不存在的键时,会调用一个预设的工厂函数来创建默认值。
defaultdict 完整 API
| 方法 / 属性 | 描述 |
|---|---|
defaultdict([default_factory[, ...]]) | 构造函数。default_factory 是一个可调用对象(如 list, int),用于生成默认值。 |
default_factory (属性) | 存储构造时传入的默认值工厂函数。 |
__missing__(key) (特殊方法) | 当通过 d[key] 访问不存在的 key 时被调用。它会调用 default_factory,将新值存入字典并返回。 |
copy() | 返回 defaultdict 的一个浅拷贝。 |
get(key[, default]) | (与 dict 行为一致) 如果 key 不存在,返回 default (默认为 None),不会调用 default_factory。 |
继承自 dict 的方法 | keys(), values(), items(), pop(), clear() 等所有标准字典方法。 |
defaultdict 代码示例
from collections import defaultdict
# 1. 使用 list 作为工厂函数进行分组
s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
colors = defaultdict(list)
for k, v in s:
colors[k].append(v)
print(f"分组结果: {colors}")
# 输出: 分组结果: defaultdict(<class 'list'>, {'red': [1, 3, 1], 'blue': [2, 4, 4]})
# 2. 使用 int 作为工厂函数进行计数
s = 'mississippi'
counts = defaultdict(int)
for k in s:
counts[k] += 1
print(f"\n计数结果: {counts}")
# 输出: 计数结果: defaultdict(<class 'int'>, {'m': 1, 'i': 4, 's': 4, 'p': 2})
# 3. get() 方法的行为
print(f"\n访问存在的 'i': {counts['i']}") # -> 4
print(f"访问不存在的 'x' (使用[]): {counts['x']}") # -> 0 (调用了int(), 并将'x':0加入字典)
print(f"字典现在包含 'x': {counts}")
# 使用 get() 访问不存在的 'y'
print(f"使用 get() 访问 'y': {counts.get('y')}") # -> None (不会调用工厂函数)
print(f"字典内容不变: {counts}") # 'y' 不会被加入
五、 有序字典 (OrderedDict)
dict 的子类,会记住键的插入顺序。
注意:自 Python 3.7 起,标准 dict 也保证有序。OrderedDict 的优势在于其提供了专门用于重新排序的方法。
OrderedDict 完整 API
| 方法 / 属性 | 描述 |
|---|---|
popitem(last=True) | (重写 dict 方法) 移除并返回一个 (key, value) 对。如果 last 为 True (默认),按后进先出 (LIFO) 顺序返回;如果为 False,按先进先出 (FIFO) 顺序返回。 |
move_to_end(key, last=True) | 将指定的 key 移动到字典的一端。如果 last 为 True (默认),移动到右端;如果为 False,移动到左端。 |
reversed(od) (内置函数) | OrderedDict 支持逆序迭代。 |
继承自 dict 的方法 | keys(), values(), items(), pop(), clear() 等所有标准字典方法,且它们都遵循字典的顺序。 |
OrderedDict 代码示例
from collections import OrderedDict
# 模拟 LRU (最近最少使用) 缓存
cache = OrderedDict()
cache_size = 3
def access_cache(key, value):
"""访问或添加缓存项"""
if key in cache:
# 如果已存在,移动到末尾表示最近使用
cache.move_to_end(key)
print(f"命中缓存: '{key}'")
else:
# 如果缓存已满,移除最旧的项 (FIFO)
if len(cache) >= cache_size:
oldest_key, oldest_val = cache.popitem(last=False)
print(f"缓存已满, 移除最旧项: ('{oldest_key}')")
# 添加新项到末尾
cache[key] = value
print(f"添加新项: '{key}'")
print(f" 当前缓存顺序: {' '.join(cache.keys())}")
access_cache('A', 1)
access_cache('B', 2)
access_cache('C', 3)
access_cache('A', 1) # 命中,A移动到末尾
access_cache('D', 4) # 满了,移除最旧的B
六、 映射链 (ChainMap)
将多个字典或其他映射组合在一起,创建一个单一的、可更新的视图。
ChainMap 完整 API
| 方法 / 属性 | 描述 |
|---|---|
ChainMap(*maps) | 构造函数。传入一个或多个字典。 |
maps (属性) | 一个可更新的映射列表,按搜索顺序排列。 |
new_child(m=None) | 返回一个新的 ChainMap,它在当前 ChainMap 的前面添加了一个新的映射 m(默认为空字典)。 |
parents (属性) | 返回一个新的 ChainMap,它包含了当前 ChainMap 中除了第一个映射之外的所有映射。 |
__setitem__ / __delitem__ | (重要) 写入和删除操作永远只作用于 maps 列表中的第一个映射。 |
继承自 dict 的方法 | get(), keys(), values(), items() 等所有只读的字典方法。 |
ChainMap 代码示例
from collections import ChainMap
# 1. 设置多层配置
default_config = {'user': 'guest', 'theme': 'light', 'timeout': 30}
user_config = {'user': 'admin', 'theme': 'dark'}
config = ChainMap(user_config, default_config)
# 2. 读取配置 (按顺序查找)
print(f"用户: {config['user']}") # -> 'admin' (来自 user_config)
print(f"主题: {config['theme']}") # -> 'dark' (来自 user_config)
print(f"超时: {config['timeout']}") # -> 30 (来自 default_config)
# 3. 修改配置 (只影响第一个字典)
config['theme'] = 'blue'
print(f"\n修改后的 user_config: {user_config}")
print(f"default_config 未受影响: {default_config}")
# 4. new_child() 和 parents
# 创建一个临时上下文,比如用于一个特定请求
session_config = config.new_child({'session_id': 12345})
print(f"\n会话ID: {session_config['session_id']}")
print(f"在会话中读取用户: {session_config['user']}")
# 使用 parents 跳过第一层
parent_config = session_config.parents
print(f"父级配置中的用户: {parent_config['user']}")
七、 用户自定义容器 (UserDict, UserList, UserString)
这三个类是 dict, list, str 的简单包装器,主要目的是方便用户创建这些内置类型的子类。其核心数据存储在 .data 属性中。
User* 类 API
| 类 | 核心属性 | 描述 |
|---|---|---|
UserDict([initialdata]) | .data (一个 dict) | 封装一个字典对象。所有字典方法都已实现,并将操作委托给 .data。 |
UserList([list]) | .data (一个 list) | 封装一个列表对象。所有可变序列方法都已实现,并将操作委托给 .data。 |
UserString(seq) | .data (一个 str) | 封装一个字符串对象。所有字符串方法都已实现,并将操作委托给 .data。 |
User* 类代码示例
from collections import UserList
class NonNegativeList(UserList):
"""
一个自定义列表,它在添加或插入元素时
不允许负数存在。
"""
def _check_value(self, value):
if isinstance(value, (int, float)) and value < 0:
raise ValueError("列表中不允许存在负数。")
def append(self, item):
self._check_value(item)
# self.data 是底层的真实列表
self.data.append(item)
def insert(self, i, item):
self._check_value(item)
self.data.insert(i, item)
def __setitem__(self, i, item):
self._check_value(item)
self.data[i] = item
# 使用自定义列表
my_list = NonNegativeList([1, 2, 3])
my_list.append(5)
print(my_list) # -> [1, 2, 3, 5]
try:
my_list.insert(0, -10)
except ValueError as e:
print(f"错误: {e}") # -> 错误: 列表中不允许存在负数。
# 底层数据可以通过 .data 访问
print(f"底层数据: {my_list.data}") # -> [1, 2, 3, 5]
更多推荐

所有评论(0)