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

python 中的 collections 使用详解

1、collections 模块中的 defaultdict

1.1 defaultdict 功能

可以设置一个默认值作为字典中新key的默认值。该默认值可以是任何对象, 包括函数、列表、元组、集合等。默认值不需要像dict那样事先定义,因为它在需要的时候会自动创建
使用defaultdict,可以简化代码并提高代码的可读性,而且可以防止KeyError异常的出现。同时,defaultdict的性能与普通字典相当,因为底层实现并不影响字典的性能。

1.2 底层原理

重写了字典的__missing__方法。当访问字典中不存在的key时,__missing__方法负责返回默认值。因此,defaultdict通过继承dict,重载了__missing__方法,以提供默认值。

1.3 简单使用和解释以及举例

from collections import defaultdictdata_dic = defaultdict(list)       # default_factory默认是None, 这里default_factory默认是None赋值为列表
data_dic['name'].append("java")
data_dic['name'].append("python")
data_dic['name'].append("go")
data_dic['test_num'].append(1)
data_dic['test_num'].append(2)# 虽然default_factory是list,但是它并不限制data_dic中键的类型,可以添加任何类型的键和值
data_dic['category'] = "IT"print(data_dic)
# 打印的是一个defaultdict的对象,和字典一样的用法,也可以用 dict(data_dic) 将其转化为字典,但没必要,defaultdict对象和字典一样的用法
# 打印结果:defaultdict(<class 'list'>, {'name': ['java', 'python', 'go'], 'test_num': [1, 2], 'category': 'IT'})
print(data_dic['category'])# data_dic中还没有 age 这个键,那么default_factory就会自动生成一个空列表作为该键的值
print(data_dic['age'])

2、collections 模块中的 OrderedDict

2.1 OrderedDict 功能

OrderedDict是Python中collections模块中的一种字典,它可以按照元素添加的顺序来存储键值对,保证了元素的顺序性。 与Python中普通字典不同的是,OrderedDict中的元素顺序是有序的,而且支持所有字典的操作。
OrderedDict类的优点是能够维护元素的有序性,缺点是存储元素时需要使用双向链表,因此需要比字典类占用更多的内存空间
字典所拥有的方法 OrderedDict 也同样拥有

2.2 OrderedDict 示例

  • 有序字典,按照元素添加顺序打印键值对
from collections import OrderedDictd = OrderedDict()
d['python'] = 1
d['java'] = 2
d['go'] = 3
d['php'] = 4for key, value in d.items():print(key, value)# 打印结果
# python 1
# java 2
# go 3
# php 4
  • 用 OrderedDict 实现先进先出的队列
from collections import OrderedDictclass FIFO(OrderedDict):def __init__(self, capacity):super().__init__()self.capacity = capacitydef __setitem__(self, key, value):if len(self) >= self.capacity:  # 容量已满self.popitem(last=False)  # 删除最早的元素,即队首元素super().__setitem__(key, value)q = FIFO(3)
q['a'] = 1
q['b'] = 2
q['c'] = 3
print(q)  # 输出:FIFO([('a', 1), ('b', 2), ('c', 3)])
q['d'] = 4
print(q)  # 输出:FIFO([('b', 2), ('c', 3), ('d', 4)])
  • popitem()
popitem()方法用于弹出最后插入的元素。它接受一个可选的参数last,用于指定弹出的是最后插入的元素还是第一个插入的元素。
from collections import OrderedDictordered_dict = OrderedDict({'a': 1, 'c': 3, 'b': 2})
print(ordered_dict.popitem())  # ('b', 2)
print(ordered_dict.popitem(last=False))  # ('a', 1)
  • move_to_end()
move_to_end()方法可以将OrderedDict中的某个元素移动到双向链表的尾部或头部。
它接受两个可选参数,一个是key,指定要移动的元素;另一个是last,指定移动方向,
如果last为True,则移动到链表的末尾;
如果last为False,则移动到链表的头部。
1
from collections import OrderedDictordered_dict = OrderedDict({'a': 1, 'c': 3, 'b': 2})
ordered_dict.move_to_end('a')  # 将'a'元素移动到OrderedDict的末尾
print(list(ordered_dict.keys()))  # ['c', 'b', 'a']
ordered_dict.move_to_end('a', last=False)  # 将'a'元素移动到OrderedDict的头部
print(list(ordered_dict.keys()))  # ['a', 'c', 'b']

3、collections 模块中的 Counter

3.1 Counter 功能

Counter类型可以接受一个可迭代对象作为参数,并对其中的元素进行计数。同时,还可以接受一个字典对象作为参数,用于初始化计数器。

from collections import Counter# 通过可迭代对象初始化计数器
c1 = Counter('hello')
print(c1)  # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})# 通过字典对象初始化计数器
c2 = Counter({'red': 4, 'blue': 2})
print(c2)  # Counter({'red': 4, 'blue': 2})

Counter类型还提供了一些有用的方法,例如:

  • elements():返回一个迭代器,其中包含每个元素的重复次数。如果重复次数为0或负数,则不会返回该元素。
  • most_common([n]):返回一个包含n个最常见元素及其计数的列表。如果n为空,则返回所有元素及其计数的列表。
  • subtract([iterable-or-mapping]):从计数器中减去指定的元素或计数器。这个方法会修改计数器本身。

ChainMap

chainMap 属于Python collections 模块下的一个子类,作用是将多个字典,组织成一个字典。当查询时,会按照构造时传入的字典的顺序进行查询。它比使用这些字典创建一个新字典要快。

简单示例

# 导入ChainMap模块
from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
# 将h1, h2组织成一个字典
h = ChainMap(h1, h2)
# 在第一个字典中查到了"a"这个key,返回该key对应的value
print(h["a"])
# 1
# 在第一个字典中没有查到了"a"这个key,然后在第二个字典的中查到了这个key,返回该key对应的value
print(h["d"])
#30

什么时候使用呢?

在Python中,配置文件通常是字典,系统配置和个人私有配置同时存在时候,可以使用ChainMap来构造出最终配置文件,构造时候个人私有配置在前,系统配置在后。这样,在使用的时候,个人配置就能覆盖系统配置。

常用操作

初始化:chain_map = ChainMap(*maps)

传入若干个字典,用来初始化。例如:chain_map = ChainMap(h1, h2)。这样就将多个字典组合在一起了。如果在初始化的时候,没有传入字典参数,则默认传入一个空字典。底层是将传入字典的引用保存在一个列表中。

查询:查询时,依次查询每个字典,直到一个键被找到,并返回该值。

from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
h = ChainMap(h1, h2)
# 搜索操作会依次对字典进行搜索,返回第一个值
print(h["a"])
# 1
print(h["d"])
#30

这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

新增:新增键值对只操作第一个字典。

from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
h = ChainMap(h1, h2)
# 新增操作只会对第一个字典进行操作,因为保存的是引用,因此,本质上是原字典执行的新增操作
h["x"] = 10000
print(h)# 只对第一个字典进行新增
# ChainMap({'a': 1, 'b': 2, 'c': 3, 'x': 10000}, {'a': 10, 'b': 20, 'd': 30})
print(h1)
# {'a': 1, 'b': 2, 'c': 3, 'x': 10000}

这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

更新:更新键值对只会操作第一个字典。

from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
h = ChainMap(h1, h2)
# 更新操作只会对第一个字典进行操作,因为保存的是引用,因此,本质上是原字典执行的更新操作
h["a"] = 99
print(h)
# ChainMap({'a': 99, 'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30})
print(h1)
# {'a': 99, 'b': 2, 'c': 3}

这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

删除:删除键值对只会操作第一个字典。如果操作失败,会抛出异常。

from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
h = ChainMap(h1, h2)
# 删除操作只会对第一个字典进行操作,因为保存的是引用,因此,本质上是原字典执行的删除操作
del h["a"]
print(h)
# ChainMap({'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30})
print(h1)
# {'b': 2, 'c': 3}
del h["a"]
# 抛出异常,因为只会对第一个字典进行操作,在一个字典中删除不存在的key抛出异常。(不会对后续字典进行操作)

这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

其他属性与操作

maps 属性:底层保存各个字典的列表。可以直接对该属性进行操作,实质是对原字典进行操作

from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
h = ChainMap(h1, h2)
print(h.maps)
# [{'a': 1, 'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30}]
# 使用该属性更改字典
h.maps[0]["a"] = 123
# 本质是改变原字典
print(h1)
# {'a': 123, 'b': 2, 'c': 3}     

new_child(m=None, **kwargs)方法:返回一个新的 ChainMap,字典m 位于第一位,其他位于后面,保存的是引用。如果没有指定m,相当于传入了一个空字典。调用 d.new_child() 等价于 ChainMap({}, *d.maps)。如果指定了任何关键字参数kwargs,它会更新所传入的字典。

from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
h = ChainMap(h1, h2)
# 传入的字典位于最前,传入的kwargs更新传入的字典
hh = h.new_child({"a":-1}, b=10)
# ChainMap({'a': -1, 'b': 10}, {'a': 1, 'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30})
print(hh)

parents属性:返回一个新的 ChainMap 对象,该对象等价于原对象去除了第一个字典。一个 d.parents 等价于 ChainMap(*d.maps[1:]) 。

from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
h = ChainMap(h1, h2)
hh = h.parents
print(hh)
# ChainMap({'a': 10, 'b': 20, 'd': 30})

相关文章:

  • 【C++11】右值引用 + 移动语义 + 完美转发(重点)
  • Vue - 你知道Vue组件之间是如何进行数据传递的吗
  • css伪类:last-child或:first-child不生效
  • 【数据库】MySQL数据库学习涵盖的多个方面
  • vue项目安装下载项目包,报错clear up some disk space and try again
  • python学习25:python中的元组(tuple)
  • 【C语言】——指针八:指针运算笔试题解析
  • 明日周刊-第5期
  • Unity框架,ET框架8.1版本的打包流程记录
  • Linux——gdb
  • 计算机毕业设计选题之基于SSM的旅游管理系统【源码+PPT+文档+包运行成功+部署讲解】
  • Nginx: proxy_set_header 与 add_header 区别
  • 卫星遥感监测森林植被健康度
  • 影院座位选择简易实现(uniapp)
  • 【Qt】:常用控件(一:概述和QWidget核心属性)
  • hexo+github搭建个人博客
  • Electron入门介绍
  • GraphQL学习过程应该是这样的
  • JavaScript类型识别
  • leetcode讲解--894. All Possible Full Binary Trees
  • MySQL几个简单SQL的优化
  • Node 版本管理
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • vuex 学习笔记 01
  • 构造函数(constructor)与原型链(prototype)关系
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #stm32驱动外设模块总结w5500模块
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .net流程开发平台的一些难点(1)
  • /etc/motd and /etc/issue
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @JSONField或@JsonProperty注解使用
  • @selector(..)警告提示
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • [C#]winform部署yolov5-onnx模型
  • [C#]winform制作仪表盘好用的表盘控件和使用方法
  • [C++]Leetcode17电话号码的字母组合
  • [CERC2017]Cumulative Code
  • [HOW TO]怎么在iPhone程序中实现可多选可搜索按字母排序的联系人选择器
  • [iOS]-UIKit
  • [leetcode] 3Sum
  • [NOSQL] Redis介绍
  • [python]python监听、操作键盘鼠标库pynput详细教程