Python collections模块详细教程
Python collections模块详细教程
1. 模块简介
collections模块是Python标准库中的一个重要模块,提供了一系列专门的容器数据类型,作为Python内置容器(如dict、list、set、tuple)的扩展和替代方案。这些数据类型在特定场景下使用更加便捷和高效。
主要功能包括:
- 命名元组(namedtuple)
- 双向队列(deque)
- 默认字典(defaultdict)
- 有序字典(OrderedDict)
- 计数器(Counter)
- 链式映射(ChainMap)
2. 安装与导入
collections模块是Python标准库的一部分,无需单独安装,直接导入即可使用:
from collections import namedtuple, deque, defaultdict, OrderedDict, Counter, ChainMap
3. 核心功能详解
3.1 namedtuple - 命名元组
namedtuple是一种创建具有命名字段的元组子类的工厂函数,它结合了元组的不可变性和字典的字段访问方式。
基本用法:
# 创建命名元组类
Point = namedtuple('Point', ['x', 'y'])
Person = namedtuple('Person', ['name', 'age', 'city'])
# 创建命名元组实例
p1 = Point(1, 2)
p2 = Point(x=3, y=4)
person = Person('张三', 25, '北京')
# 通过名称访问字段
print(f"p1.x = {p1.x}, p1.y = {p1.y}")
print(f"姓名: {person.name}, 年龄: {person.age}, 城市: {person.city}")
# 查看字段名
print(f"p1._fields = {p1._fields}")
# 创建新的命名元组实例(替换某些字段)
p3 = p1._replace(x=5)
print(f"替换后的点p3: {p3}")
适用场景:
- 当你需要使用元组但又希望通过名称访问字段时
- 作为轻量级的类替代方案
- 用于表示固定结构的数据
3.2 deque - 双向队列
deque(双端队列)是一种支持从两端快速添加和删除元素的数据结构,适用于需要频繁在两端操作的场景。
基本用法:
# 创建deque
dq = deque([1, 2, 3, 4, 5])
# 从右侧添加元素
dq.append(6)
# 从左侧添加元素
dq.appendleft(0)
# 从右侧移除元素
removed_right = dq.pop()
# 从左侧移除元素
removed_left = dq.popleft()
# 旋转deque
dq.rotate(2) # 向右旋转2位
dq.rotate(-1) # 向左旋转1位
# 限制deque的最大长度
limited_dq = deque(maxlen=3)
for i in range(5):
limited_dq.append(i)
适用场景:
- 实现队列和栈
- 滑动窗口算法
- 需要高效的两端操作的场景
3.3 defaultdict - 默认字典
defaultdict是dict的子类,它提供了一个默认值工厂函数,当访问不存在的键时,会自动创建该键并设置默认值。
基本用法:
# 创建defaultdict,指定默认值类型
dd_list = defaultdict(list)
dd_int = defaultdict(int)
dd_set = defaultdict(set)
# 使用不存在的键不会引发 KeyError
dd_list['fruits'].append('apple')
dd_list['fruits'].append('banana')
dd_int['count'] += 1
dd_int['count'] += 2
dd_set['numbers'].add(1)
dd_set['numbers'].add(2)
dd_set['numbers'].add(1) # 重复元素不会添加
# 自定义默认工厂函数
def default_factory():
return "未知"
dd_custom = defaultdict(default_factory)
dd_custom['name'] = '张三'
print(f"姓名: {dd_custom['name']}")
print(f"未知键的默认值: {dd_custom['unknown']}")
适用场景:
- 统计和分组数据
- 构建嵌套数据结构
- 避免手动检查键是否存在
3.4 OrderedDict - 有序字典
OrderedDict是dict的子类,它会记住键的插入顺序。在Python 3.7+中,普通字典也会保持插入顺序,但OrderedDict提供了一些额外的方法。
基本用法:
# 创建OrderedDict
od = OrderedDict()
od['first'] = 1
od['second'] = 2
od['third'] = 3
# 保持插入顺序
od['fourth'] = 4
od['fifth'] = 5
# 移动元素到末尾
od.move_to_end('second')
# 移动元素到开头
od.move_to_end('fourth', last=False)
# 比较顺序
od1 = OrderedDict([('a', 1), ('b', 2)])
od2 = OrderedDict([('b', 2), ('a', 1)])
normal_dict1 = {'a': 1, 'b': 2}
normal_dict2 = {'b': 2, 'a': 1}
print(f"OrderedDict相等性(顺序相关): {od1 == od2}")
print(f"普通字典相等性(顺序无关): {normal_dict1 == normal_dict2}")
适用场景:
- 需要保持键值对插入顺序的场景
- 需要频繁重新排序键的场景
- 当顺序比较重要时
3.5 Counter - 计数器
Counter是一个用于计数可哈希对象的容器,它是dict的子类,用于统计元素出现的次数。
基本用法:
# 创建Counter
text = "hello world"
counter = Counter(text)
# 计数列表元素
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
num_counter = Counter(numbers)
# 获取最常见的元素
print(f"最常见的3个元素: {counter.most_common(3)}")
print(f"最常见的2个数字: {num_counter.most_common(2)}")
# 更新计数
counter.update("python")
# 数学运算
counter1 = Counter(['a', 'b', 'c', 'a', 'b', 'b'])
counter2 = Counter(['a', 'b', 'c', 'c', 'd'])
print(f"相加: {counter1 + counter2}")
print(f"相减: {counter1 - counter2}")
print(f"交集: {counter1 & counter2}")
print(f"并集: {counter1 | counter2}")
适用场景:
- 统计词频
- 分析数据分布
- 计算元素出现次数
3.6 ChainMap - 链式映射
ChainMap将多个字典或映射组合成一个逻辑上的单一映射,它会按顺序搜索键。
基本用法:
# 创建多个字典
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
dict3 = {'e': 5, 'f': 6}
# 创建ChainMap
cm = ChainMap(dict1, dict2, dict3)
# 访问元素
print(f"访问'a': {cm['a']}")
print(f"访问'c': {cm['c']}")
print(f"访问'e': {cm['e']}")
# 查找键所在的字典
print(f"键'a'所在的字典索引: {cm.maps.index(dict1)}")
# 添加新映射到开头
dict4 = {'g': 7, 'h': 8}
cm_new = cm.new_child(dict4)
# 访问父ChainMap
print(f"父ChainMap: {cm_new.parents}")
适用场景:
- 合并多个配置字典
- 实现配置覆盖机制
- 管理嵌套命名空间
4. 实用示例
4.1 使用defaultdict统计单词频率
def count_words(text):
word_count = defaultdict(int)
words = text.lower().split()
for word in words:
# 移除标点符号
clean_word = ''.join(c for c in word if c.isalnum())
if clean_word:
word_count[clean_word] += 1
return dict(word_count)
sample_text = "Python is great. Python is powerful. Programming with Python is fun."
word_freq = count_words(sample_text)
print("单词频率统计:")
print(word_freq)
4.2 使用deque实现滑动窗口
def sliding_window(sequence, window_size):
window = deque(maxlen=window_size)
result = []
for item in sequence:
window.append(item)
if len(window) == window_size:
result.append(list(window))
return result
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
windows = sliding_window(data, 3)
print(f"滑动窗口(size=3): {windows}")
4.3 使用Counter分析调查数据
survey_data = ['满意', '不满意', '满意', '一般', '满意', '满意', '不满意', '一般', '一般', '满意']
satisfaction_counter = Counter(survey_data)
print(f"满意度调查结果: {satisfaction_counter}")
print(f"最受欢迎的选项: {satisfaction_counter.most_common(1)[0]}")
5. 代码优化建议
-
选择合适的容器类型:根据具体场景选择最合适的collections容器,例如:
- 需要快速两端操作时使用
deque - 需要统计频率时使用
Counter - 需要默认值时使用
defaultdict
- 需要快速两端操作时使用
-
注意内存使用:
- 使用
deque(maxlen=N)限制队列大小,避免内存溢出 - 对于大型数据集,考虑使用
Counter而不是手动计数
- 使用
-
性能考虑:
deque的append/pop操作时间复杂度为O(1),比列表更高效defaultdict避免了键存在性检查,提高了代码可读性和效率
-
代码可读性:
- 使用
namedtuple给元组字段命名,提高代码可读性 - 使用
OrderedDict保持键的顺序,使代码逻辑更清晰
- 使用
6. 常见问题与解决方案
6.1 问题:namedtuple不可修改
解决方案:使用_replace()方法创建新的namedtuple实例,而不是尝试修改现有实例。
6.2 问题:deque超出最大长度
解决方案:设置合适的maxlen参数,或在添加元素前检查当前长度。
6.3 问题:defaultdict的默认值不符合预期
解决方案:确保默认工厂函数返回正确的默认值类型。
6.4 问题:Counter计数结果不符合预期
解决方案:确保输入数据是可哈希的,对于复杂对象考虑使用frozenset或自定义哈希函数。
6.5 问题:ChainMap修改操作影响原始字典
解决方案:注意ChainMap只是引用原始字典,修改操作会影响原始数据。如需隔离修改,应创建副本。
7. 总结
collections模块提供了一系列强大的容器数据类型,它们扩展了Python的内置容器,为各种常见编程场景提供了更便捷、更高效的解决方案。通过合理使用这些工具,可以大大提高代码的可读性、性能和可维护性。
主要优势:
- 提供了专门化的容器类型,满足特定场景需求
- 简化了常见编程任务,如计数、分组、队列操作等
- 提高了代码可读性和表达能力
- 优化了特定操作的性能
collections模块是Python标准库中的重要组成部分,掌握其使用方法对于编写高质量的Python代码非常重要。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)