python进阶collections标准库使用示例详解

目录
  • 前言
  • namedtuple
    • namedtuple的由来
    • namedtuple的格式
    • namedtuple声明以及实例化
    • namedtuple的方法和属性
  • OrderedDict
    • popitem(last=True)
    • move_to_end(key, last=True)
    • 支持reversed
    • 相等测试敏感
  • defaultdict
    • 小例子1
    • 小例子2
    • 小例子3
  • Counter对象
    • 创建方式
    • elements()
    • most_common([n])
    • 应用场景
  • deque([iterable[, maxlen]])
    • deque的方法
    • deque 用法

前言

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

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

namedtuple

namedtuple的由来

因为元组的局限性:不能为元组内部的数据进行命名,所以往往我们并不知道一个元组所要表达的意义,所以引入namedtuple这个工厂函数,来构造一个带字段名的元组。namedtuple继承自tuple
命名元组赋予每个位置一个含义,提供可读性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。

namedtuple的格式

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

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

我们查看结果

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

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

user1 = User(name='jkc')
user2 = User(name='jkc2', age=20, height=198)
print(user1)
print(user2)
print(user1.name)
print(user2.age)

运行结果为

User(name='jkc', age=18, height=180)
User(name='jkc2', age=20, height=198)
jkc
20

namedtuple的方法和属性

命名元组还支持三个额外的方法和两个属性。为了防止字段名冲突,方法和属性以下划线开始。
_make(iterable)类方法从存在的序列或迭代实例创建一个新实例。

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

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

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

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

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

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

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

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

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

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

>>> d = {'name': 'jkc6', 'age': 18, 'height': 180}
>>> User(**d)
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先进先出的顺序返回键值对。

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

move_to_end(key, last=True)

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

d = OrderedDict({'status': 200, 'message': 'success'})
d.move_to_end('status', last=True)
print('移动后的字典: ', d)
d.move_to_end('status', last=False)
print('移动后的字典', d)
# 结果
移动后的字典:  OrderedDict([('message', 'success'), ('status', 200)])
移动后的字典:  OrderedDict([('status', 200), ('message', 'success')])

支持reversed

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

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

相等测试敏感

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

d1 = OrderedDict({'status': 200, 'message': 'success'})
d2 = OrderedDict({'message': 'success', 'status': 200})
d3 = {'status': 200, 'message': 'success'}
d4 = {'message': 'success', 'status': 200}
print('OrderedDict之间的比较结果: ', d1 == d2)
print('dict之间的比较结果: ', d3 == d4)
print('OrderedDict与dict的比较结果: ', d1 == d3 == d4)
# 结果
OrderedDict之间的比较结果:  False
dict之间的比较结果:  True
OrderedDict与dict的比较结果:  True

defaultdict

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

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

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

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

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

dict1 = defaultdict(int)
dict2 = defaultdict(set)
dict3 = defaultdict(str)
dict4 = defaultdict(list)
print(dict1['name'])
print(dict2['name'])
print(dict3['name'])
print(dict4['name'])

输出

0
set()

[]

小例子1

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

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

小例子2

设置default_factoryint,使defaultdict用于计数

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

小例子3

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

def constant_factory(value):
    return lambda: value
d = defaultdict(constant_factory('success'))
d.update(status=200)
var = d['message']
print(sorted(d.items()))
# 输出
[('message', 'success'), ('status', 200)]

Counter对象

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

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

创建方式

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

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

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

>>> c = Counter(['eggs', 'ham'])
>>> c['bacon']
0

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

elements()

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

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

most_common([n])

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

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

应用场景

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

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

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

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

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

>>> import re
>>> words = re.findall(r'\w+', open('log.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1180), ('and', 822), ('to', 810), ('of', 799), ('i', 688),
 ('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也可以实现同样的功能

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

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

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

以上就是python进阶collections标准库使用示例详解的详细内容,更多关于python collections标准库的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python内置模块Collections的使用教程详解

    目录 1.模块说明 2. 实战代码 (1) testNamedTuple函数 (2) testDeque函数 (3)testDefaultdict函数 (4) testOrderedDict函数 (5) testCounter函数 1.模块说明 collections 是 Python 的一个内置模块,所谓内置模块的意思是指 Python 内部封装好的模块,无需安装即可直接使用. collections 包含了一些特殊的容器,针对 Python 内置的容器,例如: list.dict.set.t

  • Python标准库之collections包的使用教程

    前言 Python为我们提供了4种基本的数据结构:list, tuple, dict, set,但是在处理数据量较大的情形的时候,这4种数据结构就明显过于单一了,比如list作为数组在某些情形插入的效率会比较低,有时候我们也需要维护一个有序的dict.所以这个时候我们就要用到Python标准库为我们提供的collections包了,它提供了多个有用的集合类,熟练掌握这些集合类,不仅可以让我们让写出的代码更加Pythonic,也可以提高我们程序的运行效率. defaultdict defaultd

  • Python中collections.Counter()的具体使用

    目录 Counter类 创建 计数值的访问与缺失的键 计数器的更新 键的删除 elements() most_common([n]) fromkeys 浅拷贝copy 算术和集合操作 常用操作 Counter类 Counter类的目的是用来跟踪值出现的次数.它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value.计数值可以是任意的Interger(包括0和负数).Counter类和其他语言的bags或multisets很相似. 创建 Counter是一个容器对象

  • Python collections.defaultdict模块用法详解

    Python中通过Key访问字典,当Key不存在时,会引发'KeyError'异常.为了避免这种情况的发生,可以使用collections类中的defaultdict()方法来为字典提供默认值. 语法格式: collections.defaultdict([default_factory[, -]]) class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): default_factory: Callable[[], _VT] 该函数返回一个类似

  • Python collections中的双向队列deque简单介绍详解

    前言 在python神书<Python+Cookbook>中有这么一段话:在队列两端插入或删除元素时间复杂度都是 O(1) ,而在列表的开头插入或删除元素的时间复杂度为 O(N). 于是就想验证下. 简单使用 基本代码 from collections import deque q = deque(maxlen=4)#有固定长度的双向队列 qq = deque() #无固定长度 print(dir(q))#看看有哪些可用方法或属性 结果: ['__add__', '__bool__', '__

  • python 中的collections.OrderedDict() 用法

    Python中的字典对象可以以"键:值"的方式存取数据.OrderedDict是它的一个子类,实现了对字典对象中元素的排序. 注意,OrderedDict的 Key 会按照插入的顺序排列,不是Key本身排序: 比如下面比较了两种方式的不同: import collections print 'Regular dictionary:' d={} d['a']='A' d['b']='B' d['c']='C' for k,v in d.items(): print k,v print '

  • python进阶collections标准库使用示例详解

    目录 前言 namedtuple namedtuple的由来 namedtuple的格式 namedtuple声明以及实例化 namedtuple的方法和属性 OrderedDict popitem(last=True) move_to_end(key, last=True) 支持reversed 相等测试敏感 defaultdict 小例子1 小例子2 小例子3 Counter对象 创建方式 elements() most_common([n]) 应用场景 deque([iterable[,

  • python可视化大屏库big_screen示例详解

    目录 big_screen 特点 安装环境 输入数据 本地运行 在线部署 对于从事数据领域的小伙伴来说,当需要阐述自己观点.展示项目成果时,我们需要在最短时间内让别人知道你的想法.我相信单调乏味的语言很难让别人快速理解.最直接有效的方式就是将数据如上图所示这样,进行可视化展现. 具体如下: big_screen 特点 便利性工具, 结构简单, 你只需传数据就可以实现数据大屏展示. 安装环境 pip install -i https://pypi.tuna.tsinghua.edu.cn/simp

  • Python中字典常用操作的示例详解

    目录 前言 初始化 合并字典 字典推导式 Collections 标准库 字典转 JSON 字典转 Pandas 前言 字典是Python必用且常用的数据结构,本文梳理常用的字典操作,看这个就够了,涉及: 初始化 合并字典 字典推导式 Collections 标准库 字典转JSON 字典转Pandas 初始化 # 最常用这种 my_object = { "a": 5, "b": 6 } # 如果你不喜欢写大括号和双引号: my_object = dict(a=5,

  • 详解Python中生成随机数据的示例详解

    目录 随机性有多随机 加密安全性 PRNG random 模块 数组 numpy.random 相关数据的生成 random模块与NumPy对照表 CSPRNG 尽可能随机 os.urandom() secrets 最佳保存方式 UUID 工程随机性的比较 在日常工作编程中存在着各种随机事件,同样在编程中生成随机数字的时候也是一样,随机有多随机呢?在涉及信息安全的情况下,它是最重要的问题之一.每当在 Python 中生成随机数据.字符串或数字时,最好至少大致了解这些数据是如何生成的. 用于在 P

  • Python+FuzzyWuzzy实现模糊匹配的示例详解

    目录 1. 前言 2. FuzzyWuzzy库介绍 2.1 fuzz模块 2.2 process模块 3. 实战应用 3.1 公司名称字段模糊匹配 3.2 省份字段模糊匹配 4. 全部函数代码 在日常开发工作中,经常会遇到这样的一个问题:要对数据中的某个字段进行匹配,但这个字段有可能会有微小的差异.比如同样是招聘岗位的数据,里面省份一栏有的写“广西”,有的写“广西壮族自治区”,甚至还有写“广西省”……为此不得不增加许多代码来处理这些情况. 今天跟大家分享FuzzyWuzzy一个简单易用的模糊字符

  • Python进阶_关于命名空间与作用域(详解)

    写在前面 如非特别说明,下文均基于Python3 命名空间与作用于跟名字的绑定相关性很大,可以结合另一篇介绍Python名字.对象及其绑定的文章. 1. 命名空间 1.1 什么是命名空间 Namespace命名空间,也称名字空间,是从名字到对象的映射.Python中,大部分的命名空间都是由字典来实现的,但是本文的不会涉及命名空间的实现.命名空间的一大作用是避免名字冲突: def fun1(): i = 1 def fun2(): i = 2 同一个模块中的两个函数中,两个同名名字i之间绝没有任何

  • python编程开发时间序列calendar模块示例详解

    目录 calendar模块 设置每周第一天-setfirstweekday 1.默认情况:礼拜一是第一天 2.设置任意一天 是否闰年-isleap 年份间的闰年数-leapdays(y1, y2) 星期几-weekday(year, month, day) monthrange(year, month) 月的日历矩阵-monthcalendar(year, month) 月的日历-prmonth(year, month, w, l) 年的日历-calendar.calendar(year) 格式

  • python机器学习Sklearn实战adaboost算法示例详解

    目录 pandas批量处理体测成绩 adaboost adaboost原理案例举例 弱分类器合并成强分类器 pandas批量处理体测成绩 import numpy as np import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt data = pd.read_excel("/Users/zhucan/Desktop/18级高一体测成绩汇总.xls") cond =

  • Python MySQL数据库基本操作及项目示例详解

    目录 一.数据库基础用法 二.项目:银行管理系统 1.进行初始化操作 2.登录检查,并选择操作 3.加入查询功能 4.加入取钱功能 5.加入存钱功能 一.数据库基础用法 要先配置环境变量,然后cmd安装:pip install pymysql 1.连接MySQL,并创建wzg库 #引入decimal模块 import pymysql #连接数据库 db=pymysql.connect(host='localhost',user='root',password='1234',charset='ut

随机推荐