当前位置: 首页 > article >正文

Python库collections详解 (一)

模块概述

模块作用

这个模块实现了一些专门化的容器,提供了对 Python 的通用内建容器 dict、list、set 和 tuple 的补充。

官方资料

collections --- 容器数据类型 — Python 3.13.2 文档

子类概览

namedtuple()创建命名元组子类的工厂函数,生成可以使用名字来访问元素内容的tuple子类
deque类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)
ChainMap类似字典(dict)的容器类,将多个映射集合到一个视图里面
Counter字典的子类,提供了可哈希对象的计数功能
OrderedDict字典的子类,保存了他们被添加的顺序,有序字典
defaultdict字典的子类,提供了一个工厂函数,为字典查询提供一个默认值
UserDict封装了字典对象,简化了字典子类化
UserList封装了列表对象,简化了列表子类化
UserString封装了字符串对象,简化了字符串子类化(中文版翻译有误)

Counter--计数器

一个计数器工具,为的是可以方便快速地计账。例如可以利用Counter分析列表中不同单词的出现次数

ls = ['y','n','n','y','y','n']
cnt = Counter()
for ch in ls:
    cnt[ch] += 1
cnt
# 结果 Counter({'y': 3, 'n': 3})

 初始化

c = Counter()                           # 一个新的空计数器  
c = Counter('gallahad')                 # 从可迭代对象创建一个新的计数器  
c = Counter({'red': 4, 'blue': 2})      # 从映射创建一个新的计数器  
c = Counter(cats=4, dogs=8)             # 从关键字参数创建一个新的计数器

 使用

查询

在使用Counter进行查询时,格式和字典一样:c['a'],区别在于如果查询不到会返回0而不是KeyError

elements()

返回一个迭代器,每个元素出现其计数器的对应次数,同时出现顺序和原顺序相同

from collections import Counter  

# 创建一个 Counter 对象  
c = Counter(['apple', 'banana', 'apple', 'orange', 'banana', 'banana'])  

# 获取元素的迭代器  
elements = list(c.elements())  

print(elements)  # 输出: ['apple', 'apple', 'banana', 'banana', 'banana', 'orange']

most_common([n])

返回一个列表,其中包含 n 个最常见的元素及出现次数,按常见程度由高到低排序。 如果 n 被省略或为 None,most_common()将返回计数器中的 所有 元素。 计数值相等的元素按首次出现的顺序排序 

提供n

from collections import Counter  

# 创建一个 Counter 对象  
c = Counter(['apple', 'banana', 'apple', 'orange', 'banana', 'banana', 'kiwi'])  

# 获取最常见的元素  
most_common_elements = c.most_common(2)  # 获取前 2 个最常见的元素  

print(most_common_elements)  # 输出: [('banana', 3), ('apple', 2)]

不提供n

# 获取所有最常见的元素  
all_common_elements = c.most_common()  

print(all_common_elements)  
# 输出: [('banana', 3), ('apple', 2), ('orange', 1), ('kiwi', 1)]

subtract([iterable-or-mapping])

减去一个可迭代对象或者映射对象中的元素,输入和输出可以为负

c = Counter(a=4, b=2, c=0, d=-2)
d = Counter(a=1, b=2, c=3, d=4)
c.subtract(d)
c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

total()

计算总数

c = Counter(a=10, b=5, c=0)
c.total()
15

update([iterable-or-mapping])

加上一个 可迭代对象 或 映射对象 (或 counter) 中的元素。

from collections import Counter  

# 创建一个 Counter 对象  
c = Counter(['apple', 'banana', 'apple'])  

print("初始计数器:", c)  # 输出: 初始计数器: Counter({'apple': 2, 'banana': 1})  

# 使用可迭代对象更新计数器  
c.update(['banana', 'kiwi', 'kiwi'])  

print("更新后的计数器 (使用可迭代对象):", c)  
# 输出: 更新后的计数器 (使用可迭代对象): Counter({'apple': 2, 'banana': 2, 'kiwi': 2})  

# 使用字典更新计数器  
c.update({'apple': 1, 'kiwi': 3})  

print("更新后的计数器 (使用字典):", c)  
# 输出: 更新后的计数器 (使用字典): Counter({'kiwi': 5, 'apple': 3, 'banana': 2})

常见字典方法都能使用

c.total()                       # 所有计数的总和  
c.clear()                       # 重置所有计数  
list(c)                         # 列出不同的元素  
set(c)                          # 转换为集合  
dict(c)                         # 转换为常规字典  
c.items()                       # 访问 (元素, 计数) 对  
Counter(dict(list_of_pairs))    # 从 (元素, 计数) 对的列表转换  
c.most_common()[:-n-1:-1]       # n 个最不常见的元素  
+c                              # 移除计数为零和负的元素

deque--双向队列

返回一个新的双向队列对象

list对象也支持类似的操作,但它们是针对快速的固定长度的操作进行优化而 pop(0) 和 insert(0, v) 操作对下层数据表示的大小和位置改变都将产生 O(n) 的内存移动开销。

初始化

d = deque('ghi')

使用

append(x)

添加 x 到右端。

from collections import deque  

d = deque()  
d.append(1)  
d.append(2)  
print(d)  # 输出: deque([1, 2])

appendleft(x)

添加 x 到左端。

d.appendleft(0)  
print(d)  # 输出: deque([0, 1, 2])

clear()

移除所有元素,使其长度为0.

copy()

创建一份浅拷贝。

count(x)

计算 deque 中元素等于 x 的个数。

d = deque([1, 2, 2, 3])  
count_of_2 = d.count(2)  
print(count_of_2)  # 输出: 2

extend(iterable)

扩展deque的右侧,通过添加iterable参数中的元素。

d.extend([4, 5])  
print(d)  # 输出: deque([1, 2, 2, 3, 4, 5])

extendleft(iterable)

扩展deque的左侧,通过添加iterable参数中的元素。注意,左添加时,在结果中iterable参数中的顺序将被反过来添加。

d.extendleft([-1, 0])  
print(d)  # 输出: deque([0, -1, 1, 2, 2, 3, 4, 5])

index(x[, start[, stop]])

返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。 返回第一个匹配项,如果未找到则引发 ValueError。

index_of_2 = d.index(2)  
print(index_of_2)  # 输出: 2

insert(ix)

在位置 i 插入 x 。

如果插入会导致一个限长 deque 超出长度 maxlen 的话,就引发一个 IndexError。

d.insert(1, 1.5)  
print(d)  # 输出: deque([0, 1.5, -1, 1, 2, 2, 3, 4, 5])

pop()

移去并且返回一个元素,deque 最右侧的那一个。 如果没有元素的话,就引发一个 IndexError。

last_element = d.pop()  
print(last_element)  # 输出: 5  
print(d)  # 输出: deque([0, 1.5, -1, 1, 2, 2, 3, 4])

popleft()

移去并且返回一个元素,deque 最左侧的那一个。 如果没有元素的话,就引发 IndexError。

first_element = d.popleft()  
print(first_element)  # 输出: 0  
print(d)  # 输出: deque([1.5, -1, 1, 2, 2, 3, 4])

remove(value)

移除找到的第一个 value。 如果没有的话就引发 ValueError。

d.remove(2)  
print(d)  # 输出: deque([1.5, -1, 1, 2, 3, 4])

reverse()

将deque逆序排列。返回 None 。

rotate(n=1)

向右循环移动 n 步。 如果 n 是负数,就向左循环。

如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。

d.rotate(2)  
print(d)  # 输出: deque([1, -1, 1.5, 4, 3, 2])

在上述操作以外,deque 还支持迭代, 封存, len(d)reversed(d)copy.copy(d)copy.deepcopy(d), 使用 in 运算符的成员检测以及下标引用例如通过 d[0] 访问首个元素等。 

有序字典--OrderDict

有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。由于内置的 dict 类获得了记住插入顺序的能力(Python 3.7 ),它们变得不那么重要了。

初始化

from collections import OrderedDict  

# 1. 无参数初始化  
od1 = OrderedDict()  
print(od1)  # 输出: OrderedDict()  

# 2. 使用可迭代对象初始化  
od2 = OrderedDict([('key1', 'value1'), ('key2', 'value2')])  
print(od2)  # 输出: OrderedDict([('key1', 'value1'), ('key2', 'value2')])  

# 3. 使用字典初始化  
od3 = OrderedDict({'key1': 'value1', 'key2': 'value2'})  
print(od3)  # 输出: OrderedDict([('key1', 'value1'), ('key2', 'value2')])  

# 4. 使用关键字参数初始化  
od4 = OrderedDict(key1='value1', key2='value2')  
print(od4)  # 输出: OrderedDict([('key1', 'value1'), ('key2', 'value2')])

使用

popitem(last = True)

移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。

from collections import OrderedDict
d = OrderedDict.fromkeys('abcde')
d.popitem()
# ('e', None)
d
# OrderedDict([('a', None), ('b', None), ('c', None), ('d', None)])
#last=False时,弹出第一个
d = OrderedDict.fromkeys('abcde')
''.join(d.keys())
# 'abcde'
d.popitem(last=False)
''.join(d.keys())
# 'bcde'

move_to_end

from collections import OrderedDict
d = OrderedDict.fromkeys('abcde')
p = ''.join(d.keys())

print(p)
# 'acdeb'

d.move_to_end('b', last=False)
''.join(d.keys())
print(p)
# 'bacde'

reversed

d = OrderedDict.fromkeys('abcde')
list(reversed(d))
['e', 'd', 'c', 'b', 'a']

可命名元组-namedtuple

生成可以使用名字来访问元素内容的tuple子类,命名元组赋予每个位置一个含义,提供可读性和自文档性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。

初始化

namedtuple(typename,field_names,*,verbose=False, rename=False, module=None)

1)typename:该参数指定所创建的tuple子类的类名,相当于用户定义了一个新类。

2)field_names:该参数是一个字符串序列,如 ['x','y']。此外,field_names 也可直接使用单个字符串代表所有字段名,多个字段名用空格、逗号隔开,如 'x y' 或 'x,y'。任何有效的 Python 标识符都可作为字段名(不能以下画线开头)。有效的标识符可由字母、数字、下画线组成,但不能以数字、下面线开头,也不能是关键字(如 return、global、pass、raise 等)。

3)rename:如果将该参数设为 True,那么无效的字段名将会被自动替换为位置名。例如指定 ['abc','def','ghi','abc'],它将会被替换为 ['abc', '_1','ghi','_3'],这是因为 def 字段名是关键字,而 abc 字段名重复了。

4)verbose:如果该参数被设为 True,那么当该子类被创建后,该类定义就被立即打印出来。

5)module:如果设置了该参数,那么该类将位于该模块下,因此该自定义类的 __module__ 属性将被设为该参数值。

案例

使用 namedtuple 创建一个表示学生的类

from collections import namedtuple  

# 定义一个名为 Student 的 namedtuple,包含字段 name, age 和 grade  
Student = namedtuple('Student', ['name', 'age', 'grade'])  

# 创建几个学生实例  
student1 = Student(name='Alice', age=20, grade='A')  
student2 = Student(name='Bob', age=22, grade='B')  
student3 = Student(name='Charlie', age=21, grade='A')  

# 打印学生信息  
print(student1)  # 输出: Student(name='Alice', age=20, grade='A')  
print(student2)  # 输出: Student(name='Bob', age=22, grade='B')  
print(student3)  # 输出: Student(name='Charlie', age=21, grade='A')  

# 访问字段  
print(f"{student1.name} is {student1.age} years old and received a grade of {student1.grade}.")  
# 输出: Alice is 20 years old and received a grade of A.  

使用

_make(iterable)

类方法从存在的序列或迭代实例创建一个新实例。

# 使用 _make() 方法创建一个新的 Student 实例  
student_data = ['David', 23, 'A-']  
student4 = Student._make(student_data)  
print(student4)  
# 输出: Student(name='David', age=23, grade='A-')  

_asdict()

返回一个新的 dict ,它将字段名称映射到它们对应的值:

# 使用 _asdict() 方法将 namedtuple 转换为字典  
student_dict = student1._asdict()  
print(student_dict)  
# 输出: {'name': 'Alice', 'age': 20, 'grade': 'A'}  

_replace(**kwargs)

返回一个新的命名元组实例,并将指定域替换为新的值

# 使用 _replace() 方法创建一个新的实例,修改某个字段  
student1_updated = student1._replace(grade='A+')  
print(student1_updated)  
# 输出: Student(name='Alice', age=20, grade='A+')  

http://www.kler.cn/a/570182.html

相关文章:

  • DeepBI:AI驱动的亚马逊智能决策引擎
  • 如何合理设置请求间隔?
  • 【Prometheus】prometheus如何监控k8s集群
  • 安卓基础组件Looper - 02 native层面的剖析
  • 失去的讨论区
  • Oracle 11g的部署配置
  • 字节跳动系统攻防算法岗-Flow安全内推
  • 《2025软件测试工程师面试》接口框架TestNg篇
  • 信息收集学习笔记,以及ctfshow的一些题目
  • xcode开发:Info.plist: No such file or directory 问题,苹果开发:no such file 问题解决办法
  • Spring IoC配置(xml+组件类的生命周期方法)
  • Python的那些事第三十八篇:轻量级的 Python ORM,Peewee。
  • 【和春笋一起学C++】逻辑操作符和条件操作符
  • UniApp 24点数学游戏开发实践
  • 溯源学习笔记
  • 编程题 - 亲子糖果赛【JavaScript/Node.js解法】
  • 层次聚类R复现
  • 【经验分享】Ubuntu vmware虚拟机存储空间越来越小问题(已解决)
  • 苹果廉价机型 iPhone 16e 影像系统深度解析
  • 品佳诚邀您参加 3/12『英飞凌汽车方案引领智能座舱新纪元』在线研讨会