pin_drop当前位置:知识文库 ❯ 图文
Python标准库collections:高级容器类型
一、collections模块概述
collections 是Python标准库中提供的高级容器数据类型模块。它扩展了Python内置的dict、list、tuple等基础容器,提供了更专业、更高效的数据结构。无论是计数器、默认值字典、有序字典还是双端队列,collections模块都能让代码更简洁、更高效。
该模块包含以下核心类型:Counter(计数器)、defaultdict(默认值字典)、OrderedDict(有序字典)、deque(双端队列)、namedtuple(命名元组)和 ChainMap(映射链)。
二、核心容器类型
1. Counter - 计数器
代码示例
from collections import Counter
# 创建计数器
c = Counter(iterable) # 从可迭代对象创建
c = Counter(dict) # 从字典创建
c = Counter(keyword=value) # 从关键字参数创建
# 常用方法
c.most_common(n) # 返回n个最常见元素
c.elements() # 返回所有元素的迭代器
c.update(iterable) # 更新计数
c.subtract(iterable) # 减少计数2. defaultdict - 默认值字典
代码示例
from collections import defaultdict
# 创建默认值字典
dd = defaultdict(default_factory) # 指定默认值工厂函数
# 常用工厂函数
dd = defaultdict(list) # 默认值为空列表
dd = defaultdict(int) # 默认值为0
dd = defaultdict(set) # 默认值为空集合
dd = defaultdict(lambda: "N/A") # 默认自定义值3. OrderedDict - 有序字典
代码示例
from collections import OrderedDict
# 创建有序字典
od = OrderedDict()
od = OrderedDict(iterable)
# 特殊方法
od.move_to_end(key, last=True) # 移动键到末尾/开头
od.popitem(last=True) # 弹出最后一个/第一个键值对4. deque - 双端队列
代码示例
from collections import deque
# 创建双端队列
dq = deque(iterable, maxlen=None)
# 常用方法
dq.append(x) / dq.appendleft(x) # 右端/左端添加
dq.pop() / dq.popleft() # 右端/左端弹出
dq.rotate(n) # 旋转队列
dq.extend(iterable) # 扩展队列5. namedtuple - 命名元组
代码示例
from collections import namedtuple
# 创建命名元组类
Point = namedtuple('Point', ['x', 'y'])
# 或
Point = namedtuple('Point', 'x y')
# 创建实例
p = Point(1, 2)
print(p.x, p.y) # 通过属性访问三、基本用法详解
Counter 统计词频
代码示例
from collections import Counter
text = "python is great python is fun python is powerful"
words = text.split()
# 统计词频
word_counts = Counter(words)
print("词频统计:")
print(word_counts)
# 获取最常见的3个词
print("\n最常见的3个词:")
print(word_counts.most_common(3))
# 从列表创建
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
num_counts = Counter(numbers)
print("\n数字频率:")
print(num_counts.most_common())defaultdict 分组数据
代码示例
from collections import defaultdict
# 按首字母分组单词
words = ["apple", "banana", "avocado", "cherry", "blueberry", "apricot"]
# 使用defaultdict,无需检查键是否存在
groups = defaultdict(list)
for word in words:
groups[word[0]].append(word)
print("按首字母分组:")
for letter, words_list in groups.items():
print(f" {letter}: {words_list}")
# 统计每个学生的成绩
scores = defaultdict(list)
records = [
("张三", 85), ("李四", 92), ("张三", 78),
("王五", 90), ("李四", 88), ("张三", 95)
]
for name, score in records:
scores[name].append(score)
print("\n学生成绩:")
for name, score_list in scores.items():
avg = sum(score_list) / len(score_list)
print(f" {name}: {score_list}, 平均: {avg:.1f}")deque 双端队列操作
代码示例
from collections import deque
# 创建双端队列
dq = deque([1, 2, 3, 4, 5])
print(f"初始队列: {dq}")
# 两端操作
dq.append(6) # 右端添加
dq.appendleft(0) # 左端添加
print(f"添加后: {dq}")
dq.pop() # 右端弹出
dq.popleft() # 左端弹出
print(f"弹出后: {dq}")
# 旋转
dq.rotate(2) # 向右旋转2步
print(f"右旋2步: {dq}")
dq.rotate(-1) # 向左旋转1步
print(f"左旋1步: {dq}")
# 限制长度(自动丢弃)
limited_dq = deque(maxlen=3)
for i in range(5):
limited_dq.append(i)
print(f"限制长度为3的队列: {limited_dq}")四、完整代码示例
示例1:使用namedtuple创建数据结构
代码示例
from collections import namedtuple
# 定义学生命名元组
Student = namedtuple('Student', ['name', 'age', 'grade', 'major'])
# 创建学生实例
students = [
Student("张三", 20, 85, "计算机科学"),
Student("李四", 21, 92, "数学"),
Student("王五", 19, 78, "物理"),
Student("赵六", 22, 95, "计算机科学"),
]
# 按成绩排序
sorted_students = sorted(students, key=lambda s: s.grade, reverse=True)
print("按成绩排序:")
for student in sorted_students:
print(f" {student.name} ({student.major}): {student.grade}分")
# 查找特定专业的学生
cs_students = [s for s in students if s.major == "计算机科学"]
print(f"\n计算机科学专业学生: {[s.name for s in cs_students]}")示例2:文本分析工具
代码示例
from collections import Counter, defaultdict
import re
def analyze_text(text):
"""分析文本的词频、字符分布和常见搭配"""
# 清理文本并分词
words = re.findall(r'\b\w+\b', text.lower())
# 词频统计
word_freq = Counter(words)
# 常见双词搭配
bigrams = Counter(zip(words, words[1:]))
# 按首字母分组
alpha_groups = defaultdict(list)
for word in set(words):
alpha_groups[word[0]].append(word)
return {
"total_words": len(words),
"unique_words": len(word_freq),
"top_10_words": word_freq.most_common(10),
"top_5_bigrams": bigrams.most_common(5),
"alphabet_groups": dict(alpha_groups)
}
# 测试文本
sample_text = """
Python is a great programming language. Python is used in web development,
data science, artificial intelligence, and automation. Python is easy to
learn and has a large community. Many companies use Python for their projects.
"""
result = analyze_text(sample_text)
print(f"总词数: {result['total_words']}")
print(f"唯一词数: {result['unique_words']}")
print(f"\n前10高频词:")
for word, count in result['top_10_words']:
print(f" {word}: {count}")
print(f"\n前5常见搭配:")
for (w1, w2), count in result['top_5_bigrams']:
print(f" {w1} {w2}: {count}")示例3:实现LRU缓存
代码示例
from collections import OrderedDict
class LRUCache:
"""使用OrderedDict实现LRU缓存"""
def __init__(self, capacity):
self.cache = OrderedDict()
self.capacity = capacity
def get(self, key):
"""获取缓存值,如果存在则移到末尾(最近使用)"""
if key not in self.cache:
return None
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key, value):
"""添加或更新缓存"""
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
# 超出容量,删除最久未使用的(开头)
if len(self.cache) > self.capacity:
removed = self.cache.popitem(last=False)
print(f"缓存已满,删除: {removed[0]}")
def display(self):
"""显示当前缓存状态"""
print(f"缓存内容: {dict(self.cache)}")
# 测试LRU缓存
cache = LRUCache(3)
cache.put("A", 1)
cache.put("B", 2)
cache.put("C", 3)
cache.display()
cache.get("A") # 访问A,A变为最近使用
cache.put("D", 4) # 超出容量,删除B(最久未使用)
cache.display()
print(f"获取A: {cache.get('A')}")
print(f"获取B: {cache.get('B')}") # B已被删除示例4:Counter的数学运算
代码示例
from collections import Counter
# 两个计数器
c1 = Counter(a=3, b=1, c=5)
c2 = Counter(a=1, b=2, d=3)
print("c1:", c1)
print("c2:", c2)
# 加法:合并计数
print(f"\n相加: {c1 + c2}")
# 减法:相减(只保留正数)
print(f"相减: {c1 - c2}")
# 交集:取最小值
print(f"交集: {c1 & c2}")
# 并集:取最大值
print(f"并集: {c1 | c2}")
# 实际例子:对比两个用户的兴趣爱好
user1_interests = Counter(["python", "javascript", "react", "python", "django"])
user2_interests = Counter(["python", "java", "react", "python", "spring"])
common = user1_interests & user2_interests
print(f"\n共同兴趣: {list(common.elements())}")五、注意事项与最佳实践
注意1:Python 3.7+ 的内置
dict已经保持插入顺序。如果只需要保持顺序,普通dict已足够;OrderedDict的优势在于move_to_end()和有序popitem()功能。
注意2:
deque的两端操作时间复杂度为 O(1),而列表的pop(0)或insert(0, x)是 O(n)。需要频繁操作队列时应使用deque。
注意3:
Counter减法运算可能产生负值计数,使用c1 - c2会自动过滤掉零和负值,但直接修改计数(c[key] -= n)不会自动过滤。
注意4:
namedtuple是不可变的,创建后不能修改字段值。如果需要可变版本,可以考虑使用dataclass(Python 3.7+)。
小贴士
Python 3.7+ 的 dataclasses 模块可以作为 namedtuple 的现代替代品,支持默认值、可变字段、类型注解等更丰富的功能。对于新的项目,推荐优先使用 @dataclass 装饰器来创建数据类。
六、小结
-
Counter:专门用于计数统计,支持
most_common()和数学运算 -
defaultdict:自动为不存在的键创建默认值,避免KeyError
-
OrderedDict:支持键顺序操作,适合实现LRU缓存
-
deque:双端队列,两端操作均为O(1),适合队列和栈
-
namedtuple:创建轻量级不可变对象,可通过属性名访问
七、练习题
练习1
编写一个程序,读取一个文本文件,使用Counter统计最常见的10个单词,并按出现频率降序输出。
练习2
使用deque实现一个滑动窗口最大值算法:给定一个整数数组和一个窗口大小k,找出每个滑动窗口中的最大值。
练习3
使用namedtuple或dataclass创建一个"商品"数据结构,包含名称、价格、库存等字段。编写函数实现:按价格排序、按库存筛选、计算总库存价值等功能。
常见问题
Python 3.7+还需要使用OrderedDict吗?
如果只是需要保持插入顺序,普通dict已经足够(Python 3.7+保证)。但如果你需要 move_to_end() 或有序的 popitem() 功能,或者需要反向迭代(reversed(od)),仍然需要使用OrderedDict。
deque和list有什么区别?什么时候用deque?
deque 在两端添加和弹出的操作时间复杂度为 O(1),而list的 pop(0) 是 O(n)。当需要频繁在列表头部插入/删除元素时(如实现队列),应使用deque。如果只在末尾操作,list更高效。
Counter的most_common()返回列表还是字典?
most_common(n) 返回一个列表,列表中的每个元素是 (元素, 计数) 元组,按计数降序排列。如果不传参数,返回所有元素。Counter本身是dict的子类,可以像字典一样使用。
defaultdict的默认工厂函数什么时候被调用?
只有当访问一个不存在的键时,默认工厂函数才会被自动调用。例如 dd = defaultdict(list) 中,当访问 dd['new_key'] 时,会自动调用 list() 创建一个空列表并返回。使用 get() 方法不会触发工厂函数。
本文涉及AI创作
内容由AI创作,请仔细甄别