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)
**`c1c2`**(数学运算) 返回两个计数器的并集(取计数值的最大值)。
+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]
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐