前言

这个模块实现了特定目标的容器,以提供Python标准内建容器dict ,list ,set , 和tuple 的替代选择。

这个模块提供了以下几个函数

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

namedtuple

namedtuple的由来

因为元组的局限性:不能为元组内部的数据进行命名,所以往往我们并不知道一个元组所要表达的意义,所以引入namedtuple这个工厂函数,来构造一个带字段名的元组。namedtuple继承自tuple

命名元组赋予每个位置一个含义,提供可读性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。

namedtuple的格式

  1. collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
  • typename: 返回一个新的元组子类,名为typename。这个新的子类用于创建类元组的对象,可以通过字段名来获取属性值,同样也可以通过索引和迭代获取值。
  • field_names: 像['x', 'y'] 一样的字符串序列。另外field_names可以是一个纯字符串,用空白或逗号分隔开元素名,比如 'x y' 或者 'x, y' 。
  • rename=False: 如果rename为true,无效字段名会自动转换成_+索引值,比如 ['abc', 'def', 'ghi', 'abc'] 转换成 ['abc', '_1', 'ghi', '_3'] , 消除关键词def和重复字段名abc。
  • default=None: defaults 可以为 None 或者是一个默认值的 iterable 。default默认值赋值跟我们平常的默认值相反,default默认值是从最右边开始,比如field_names中提供了3个字段['x', 'y', 'z'],default默认值设置为(1, 2),那么我们必须为x指定1个值,y默认值为1,z默认值为2
  • module=None: 如果 module 值有定义,命名元组的 module 属性值就被设置。

namedtuple声明以及实例化

我们首先创建一个User类,定义3个字段nameageheight,并给age设置默认值为18,给height设置了默认值180

  1. User = namedtuple('User', ['name', 'age', 'height'], defaults=(18, 180))
  2. print(User.__mro__)

我们查看结果

  1. (<class '__main__.User'>, <class 'tuple'>, <class 'object'>)

可以看到我们声明的User类是继承于tuple,接下来我们创建实例

  1. user1 = User(name='jkc')
  2. user2 = User(name='jkc2', age=20, height=198)
  3. print(user1)
  4. print(user2)
  5. print(user1.name)
  6. print(user2.age)

运行结果为

  1. User(name='jkc', age=18, height=180)
  2. User(name='jkc2', age=20, height=198)
  3. jkc
  4. 20

namedtuple的方法和属性

命名元组还支持三个额外的方法和两个属性。为了防止字段名冲突,方法和属性以下划线开始。

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

  1. >>> t = ['jkc3', 25, 190]
  2. >>> User._make(t)
  3. User(name='jkc3', age=25, height=190)

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

  1. >>> user4 = User(name='jkc4', age=28, height=200)
  2. >>> user4._asdict()
  3. {'name': 'jkc4', 'age': 28, 'height': 200}

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

  1. >>> user5 = User(name='jkc5', age=30, height=210)
  2. >>> user5._replace(age=18)
  3. User(name='jkc5', age=30, height=210)

_fields 字符串元组列出了字段名。用于提醒和从现有元组创建一个新的命名元组类型

  1. >>> user5._fields
  2. ('name', 'age', 'height')

_field_defaults 字典将字段名称映射到默认值。

  1. >>> User._field_defaults
  2. {'name': 'jkc', 'age': 18, 'height': 180}

转换一个字典到命名元组,使用 ** 两星操作符

  1. >>> d = {'name': 'jkc6', 'age': 18, 'height': 180}
  2. >>> User(**d)
  3. User(name='jkc6', age=18, height=180)

OrderedDict

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

与dict类的区别

  • 常规的 dict 被设计为非常擅长映射操作。 跟踪插入顺序是次要的
  • OrderedDict 擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的。
  • 算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。 这使其适用于跟踪最近的访问(例如在 LRU cache 中)。
  • 对于 OrderedDict ,相等操作检查匹配顺序。
  • OrderedDict 类的 popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。
  • OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。
  • Python 3.8之前, dict 缺少 __reversed__() 方法。

popitem(last=True)

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

  1. from collections import OrderedDict
  2. d = OrderedDict({'status': 200, 'message': 'success'})
  3. print(f'原始的有序字典: {d}')
  4. print('被删除的键值对是: ', d.popitem(last=True)) # 后进先出
  5. print(f'被删除后的有序字典: {d}')
  6. # 结果
  7. 原始的有序字典: OrderedDict([('status', 200), ('message', 'success')])
  8. 被删除的键值对是: ('message', 'success')
  9. 被删除后的有序字典: OrderedDict([('status', 200)])
  1. from collections import OrderedDict
  2. d = OrderedDict({'status': 200, 'message': 'success'})
  3. print(f'原始的有序字典: {d}')
  4. print('被删除的键值对是: ', d.popitem(last=False)) # 先进先出
  5. print(f'被删除后的有序字典: {d}')
  6. # 结果
  7. 原始的有序字典: OrderedDict([('status', 200), ('message', 'success')])
  8. 被删除的键值对是: ('status', 200)
  9. 被删除后的有序字典: OrderedDict([('message', 'success')])

move_to_end(key, last=True)

将现有 key 移动到有序字典的任一端。 如果 last 为真值(默认)则将元素移至末尾;如果 last 为假值则将元素移至开头。如果 key 不存在则会触发 KeyError:

  1. d = OrderedDict({'status': 200, 'message': 'success'})
  2. d.move_to_end('status', last=True)
  3. print('移动后的字典: ', d)
  4. d.move_to_end('status', last=False)
  5. print('移动后的字典', d)
  6. # 结果
  7. 移动后的字典: OrderedDict([('message', 'success'), ('status', 200)])
  8. 移动后的字典: OrderedDict([('status', 200), ('message', 'success')])

支持reversed

相对于通常的映射方法,有序字典还另外提供了逆序迭代的支持,通过 reversed()

  1. d = OrderedDict({'status': 200, 'message': 'success'})
  2. print({key: value for key, value in reversed(d.items())})
  3. # 结果
  4. {'message': 'success', 'status': 200}

相等测试敏感

OrderedDict 之间的相等测试是顺序敏感的

  1. d1 = OrderedDict({'status': 200, 'message': 'success'})
  2. d2 = OrderedDict({'message': 'success', 'status': 200})
  3. d3 = {'status': 200, 'message': 'success'}
  4. d4 = {'message': 'success', 'status': 200}
  5. print('OrderedDict之间的比较结果: ', d1 == d2)
  6. print('dict之间的比较结果: ', d3 == d4)
  7. print('OrderedDict与dict的比较结果: ', d1 == d3 == d4)
  8. # 结果
  9. OrderedDict之间的比较结果: False
  10. dict之间的比较结果: True
  11. OrderedDictdict的比较结果: True

defaultdict

返回一个新的类似字典的对象。 defaultdict 是内置 dict 类的子类。它重载了一个方法并添加了一个可写的实例变量。其余的功能与 dict 类相同

defaultdict的作用

我们看名字就知道defaultdict的作用是为字典提供一个默认的值,我们正常情况下访问一个字典的key,如果字典中没有这个key会报错

  1. >>> dict1 = {}
  2. >>> dict1['name']
  3. Traceback (most recent call last):
  4. File "<pyshell#1>", line 1, in <module>
  5. dict1['name']
  6. KeyError: 'name'
  7. >>>

此时我们就可以使用defaultdict,它包含一个名为 default_factory 的属性,构造时,第一个参数用于为该属性提供初始值,默认为 None

这个default_factory可以是listsetstr,也可以是自定义的函数,作用是当key不存在时,返回的是工厂函数的默认值,比如list对应[ ],str对应的是空字符串,set对应set( ),int对应0

  1. dict1 = defaultdict(int)
  2. dict2 = defaultdict(set)
  3. dict3 = defaultdict(str)
  4. dict4 = defaultdict(list)
  5. print(dict1['name'])
  6. print(dict2['name'])
  7. print(dict3['name'])
  8. print(dict4['name'])

输出

  1. 0
  2. set()
  3. []

小例子1

使用 list 作为 default_factory,我们可以很轻松地将(键-值对组成的)序列转换为(键-列表组成的)字典:

  1. >>> from collections import defaultdict
  2. >>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
  3. >>> d = defaultdict(list)
  4. >>> for k, v in s:
  5. d[k].append(v)
  6. >>> sorted(d.items())
  7. [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

小例子2

设置 default_factoryint,使 defaultdict 用于计数

  1. >>> s = 'aiibiicii'
  2. >>> d = defaultdict(int)
  3. >>> for k in s:
  4. d[k] += 1
  5. >>> sorted(d.items())
  6. [('a', 1), ('b', 1), ('c', 1), ('i', 6)]

小例子3

如果你需要自己定义一个返回值,你可以创建1个函数,设置自定义的返回值

  1. def constant_factory(value):
  2. return lambda: value
  3. d = defaultdict(constant_factory('success'))
  4. d.update(status=200)
  5. var = d['message']
  6. print(sorted(d.items()))
  7. # 输出
  8. [('message', 'success'), ('status', 200)]

Counter对象

它一个计数器工具提供快速和方便的计数。

它是 dict 的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。计数可以是任何整数值,包括0和负数。

创建方式

元素从一个 iterable 被计数或从其他的 mapping (or counter)初始化:

  1. c = Counter() # a new, empty counter
  2. c = Counter('gallahad') # a new counter from an iterable
  3. c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping
  4. c = Counter(cats=4, dogs=8) # a new counter from keyword args

如果引用的键没有任何记录,就返回一个0,而不是弹出一个 KeyError

  1. >>> c = Counter(['eggs', 'ham'])
  2. >>> c['bacon']
  3. 0

作为 dict 的子类,Counter 继承了记住插入顺序的功能。 Counter 对象进行数学运算时同样会保持顺序。 结果会先按每个元素在运算符左边的出现时间排序,然后再按其在运算符右边的出现时间排序。

elements()

返回一个迭代器,其中每个元素将重复出现计数值所指定次。 元素会按首次出现的顺序返回。 如果一个元素的计数值小于一,elements() 将会忽略它。

  1. >>> c = Counter(a=4, b=2, c=0, d=-2)
  2. >>> list(c.elements())
  3. ['a', 'a', 'a', 'a', 'b', 'b']

most_common([n])

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

  1. >>> Counter('abracadabra').most_common()
  2. [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]
  3. >>> Counter('abracadabra').most_common(2)
  4. [('a', 5), ('b', 2)]

应用场景

Counter对象一般有以下两种应用场景

1. 统计单词在列表中的出现次数

  1. >>> count = Counter()
  2. >>> list1 = ['red', 'blue', 'red', 'green', 'blue', 'blue']
  3. >>> for word in list1:
  4. count[word] += 1
  5. >>> count
  6. Counter({'blue': 3, 'red': 2, 'green': 1})

count[word]因为没有在Counter对象中,所以默认情况下会给他赋值为0,因此可以统计出单词出现的次数

2. 找出文件中最常见的十个单词

  1. >>> import re
  2. >>> words = re.findall(r'\w+', open('log.txt').read().lower())
  3. >>> Counter(words).most_common(10)
  4. [('the', 1180), ('and', 822), ('to', 810), ('of', 799), ('i', 688),
  5. ('you', 510), ('a', 508), ('my', 500), ('yes', 406), ('in', 318)]

deque([iterable[, maxlen]])

返回一个新的双向队列对象,从左到右初始化(用方法 append()) ,从 iterable (迭代对象) 数据创建。如果 iterable 没有指定,新队列为空。

Deque队列是由栈或者queue队列生成的。Deque 支持线程安全,内存高效添加(append)和弹出(pop),从两端都可以,两个方向的大概开销都是 O(1) 复杂度。

虽然 list 对象也支持类似操作,不过这里优化了定长操作和 pop(0)insert(0, v) 的开销。它们引起 O(n) 内存移动的操作,改变底层数据表达的大小和位置。

如果 maxlen 没有指定或者是 Nonedeques 可以增长到任意长度。否则,deque就限定到指定最大长度。一旦限定长度的deque满了,当新项加入时,同样数量的项就从另一端弹出。

deque的方法

双向队列(deque)对象支持很多方法,大部分方法list都有

方法名 作用
append(x) 添加 x 到右端
appendleft(x) 添加 x 到左端
clear() 移除所有元素,使其长度为0
copy() 创建一份浅拷贝
count(x) 计算 deque 中元素等于 x 的个数
extend(iterable) 扩展deque的右侧,通过添加iterable参数中的元素
extendleft(iterable) 扩展deque的左侧,通过添加iterable参数中的元素。注意,左添加时,在结果中iterable参数中的顺序将被反过来添加
index(x[, start[, stop]]) 返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。 返回第一个匹配项,如果未找到则引发 ValueError
insert(i, x) 在位置 i 插入 x,如果插入会导致一个限长 deque 超出长度 maxlen 的话,就引发一个 IndexError。
pop() 移去并且返回一个元素,deque 最右侧的那一个。 如果没有元素的话,就引发一个 IndexError
popleft() 移去并且返回一个元素,deque 最左侧的那一个。 如果没有元素的话,就引发 IndexError
remove(value) 移除找到的第一个 value。 如果没有的话就引发 ValueError
reverse() 将deque逆序排列。返回 None 。
rotate(n=1) 向右循环移动 n 步。 如果 n 是负数,就向左循环。如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft())
maxlen Deque的最大尺寸,如果没有限定的话就是 None

deque 用法

① linux下查看最新日志的命令是:tail -n 2 test.log,deque也可以实现同样的功能

  1. def tail(filename, n=10):
  2. with open(filename) as f:
  3. return deque(f, n)

② 维护一个近期添加元素的序列,通过从右边添加和从左边弹出

  1. def moving_average(iterable, n=3):
  2. # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
  3. # http://en.wikipedia.org/wiki/Moving_average
  4. it = iter(iterable)
  5. d = deque(itertools.islice(it, n-1))
  6. d.appendleft(0)
  7. s = sum(d)
  8. for elem in it:
  9. s += elem - d.popleft()
  10. d.append(elem)
  11. yield s / n

python进阶(26)collections标准库的更多相关文章

  1. collections标准库

    collections标准库 之前Python的第三方库用的一直很舒服,现在突然发现标准库也有collections这样的神器,可以补充list.set.dict以外的应用 1. namedtuple ...

  2. python代码规范与标准库参考

    python代码规范与标准库参考 python代码规范参考文献: http://www.runoob.com/w3cnote/google-python-styleguide.html https:/ ...

  3. python进阶06 常用问题库(2)datetime模块 base64

    python进阶06 常用问题库(2)datetime模块 base64 一.datetime模块(时间) 1.datetime.time() t=datetime.time(20,43,30,1) ...

  4. python进阶05 常用问题库(1)json os os.path模块

    python进阶05 常用问题库(1)json os os.path模块 一.json模块(数据交互) web开发和爬虫开发都离不开数据交互,web开发是做网站后台的,要跟网站前端进行数据交互 1.什 ...

  5. 【循序渐进学Python】11.常用标准库

    安装完Python之后,我们也同时获得了强大的Python标准库,通过使用这些标准库可以为我们节省大量的时间.这里是一些常用标准库的简单说明.更多的标准库的说明,可以参考Python文档 sys 模块 ...

  6. 如何美观地打印 Python 对象?这个标准库可以简单实现

    前不久,我写了一篇文章回顾 Python 中 print 的发展历史 ,提到了两条发展线索: 明线:早期的 print 语句带有 C 和 Shell 的影子,是个应用程序级的 statement,在最 ...

  7. 介绍下Python的两个标准库 os 和 sys

    import sysprint(sys.path) #python 2 中报错 ....,打印的是绝对路径(***\\python\\lib\\site-packages# 第三方库,后退一级为标准库 ...

  8. python:模块1——标准库简介

    一.文档 windows系统:IDLE中打开帮助文档 Tutorial:简单入门 Library Reference:python内置函数和标准库(看不完的,当做字典来查)(此外还有pypi(拍派社区 ...

  9. python中时间处理标准库DateTime加强版库:pendulum

    DateTime 的时区问题 Python的datetime可以处理2种类型的时间,分别为offset-naive和offset-aware.前者是指没有包含时区信息的时间,后者是指包含时区信息的时间 ...

  10. python学习23之标准库

    '''''''''标准库1.datetime 日期时间模块存在于Lib/datetime.py文件内'''from datetime import datetime,date,time #from d ...

随机推荐

  1. jsp一句话木马总结

    一.无回显的命令执行(命令执行后不会在前端页面返回数据) <%Runtime.getRuntime().exec(request.getParameter("i"));%&g ...

  2. html页面嵌套其他网站页面的方法

    直接上代码:html页面嵌套其他网站页面的方法 <div> <!--第一种:使用object标签--> <object type="text/html" ...

  3. 【深度学习】DNN房价预测

    前言 我们使用深度学习网络实现波士顿房价预测,深度学习的目的就是寻找一个合适的函数输出我们想要的结果.深度学习实际上是机器学习领域中一个研究方向,深度学习的目标是让机器能够像人一样具有分析学习的能力, ...

  4. C++11实现的数据库连接池

    它什么是? 数据库连接池负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个:类似的还有线程池. 为什么要用? 一个数据库连接对象均对应一个物理数据库连接, ...

  5. 细数实现全景图VR的几种方式(panorama/cubemap/eac)

    Three.js系列: 在元宇宙看电影,享受 VR 视觉盛宴 Three.js系列: 造个海洋球池来学习物理引擎 Three.js系列: 游戏中的第一.三人称视角 Three.js系列: 数实现全景图 ...

  6. 工具推荐-使用RedisInsight工具对Redis集群CURD操作及数据可视化和性能监控

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 0x00 快速 ...

  7. filebeat知识点

    在Filebeat的根目录下,有一个叫做filebeat.yml的文件. filebeat.inputs: - type: log enabled: true paths: - ./sample.lo ...

  8. 21. Fluentd输出插件:rewrite_tag_filter用法详解

    我们在做日志处理时,往往会从多个源服务器收集日志,然后在一个(或一组)中心服务器做日志聚合分析. 源服务器上的日志可能属于同一应用类型,也可能属于不同应用类型.我们可能需要在聚合服务器上对这些不同类型 ...

  9. docker相关总结

    Docker 的相关使用记录 一.安装docker linux环境使用yum命令安装docker 第一步:确保自己的虚拟机没有安装过docker,如果安装过的需要将原先的docker进行卸载,命令如下 ...

  10. iOS Social和Accounts简单使用

    ACAccountStore *account = [[ACAccountStore alloc] init]; ACAccountType *type = [account accountTypeW ...