一文了解 Python 中的 Collection 模块

举报
宇宙之一粟 发表于 2022/10/31 17:29:41 2022/10/31
【摘要】 Collections 模块本文将简单介绍一个 Python 模块 Collections 。这个模块实现了一些很好用的数据结构,可以帮助我们解决不同的实际问题。这个模块实现了特定目标的容器,以提供Python标准内建容器 ​​dict​​​ , ​​list​​​ , ​​set​​​ , 和 ​​tuple​​ 的替代选择。​​namedtuple()​​创建命名元组子类的工厂函数​​d...



Collections 模块

本文将简单介绍一个 Python 模块 Collections 。这个模块实现了一些很好用的数据结构,可以帮助我们解决不同的实际问题。

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

​namedtuple()​

创建命名元组子类的工厂函数

​deque​

类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)

​ChainMap​

类似字典(dict)的容器类,将多个映射集合到一个视图里面

​Counter​

字典的子类,提供了可哈希对象的计数功能

​OrderedDict​

字典的子类,保存了他们被添加的顺序

​defaultdict​

字典的子类,提供了一个工厂函数,为字典查询提供一个默认值

​UserDict​

封装了字典对象,简化了字典子类化

​UserList​

封装了列表对象,简化了列表子类化

​UserString​

封装了字符串对象,简化了字符串子类化

引入方法

import collections

可以通过​​import collections​​​导入该模块的方法,现在我们进入 ipython3 然后使用​​dir(collections)​​查看collections下都有哪些可以用的类。

In [1]: import collections

In [2]: dir(collections)
Out[2]:
['ChainMap',
 'Counter',
 'OrderedDict',
 'UserDict',
 'UserList',
 'UserString',
 '_Link',
 '_OrderedDictItemsView',
 '_OrderedDictKeysView',
 '_OrderedDictValuesView',
 '__all__',
 '__builtins__',
 '__cached__',
 '__doc__',
 '__file__',
 '__getattr__',
 '__loader__',
 '__name__',
 '__package__',
 '__path__',
 '__spec__',
 '_chain',
 '_collections_abc',
 '_count_elements',
 '_eq',
 '_heapq',
 '_iskeyword',
 '_itemgetter',
 '_nt_itemgetters',
 '_proxy',
 '_recursive_repr',
 '_repeat',
 '_starmap',
 '_sys',
 'abc',
 'defaultdict',
 'deque',
 'namedtuple']


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


Counter

Counter是一个dict子类,可帮助计算可哈希对象的值。在其中,元素存储为字典的键,值可以为零或负值。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。计数可以是任何整数值,包括0和负数。 Counter 类有点像其他语言中的 bags或multisets。

在下例中,我们可以找到文件单词出现的次数:

from collections import Counter
sentence = "I can because i think i can"
# Counter是一个简单的计数器,可以数组中统计字符出现的个数:
counts = Counter(sentence.split())
print(counts)  # Counter({'can': 2, 'i': 2, 'I': 1, 'because': 1, 'think': 1})

Counter对象有一个​​elements​​的方法,该方法在元素上返回迭代次数超过元素计数的迭代器。元素以任意顺序返回。

In [7]: c = Counter(a=4, b=2, c=0, d=-2)

In [8]: list(c.elements())
Out[8]: ['a', 'a', 'a', 'a', 'b', 'b']

​most_common​​是一种返回最常见元素及其计数(从最常见到最小)的方法。

In [9]: Counter('this is a test sentence').most_common(3)
Out[9]: [('t', 4), ('s', 4), (' ', 4)]

Counter对象有一个字典接口,如果引用的键没有任何记录,就返回一个0,而不是弹出一个 ​​KeyError​​ :

>>> c = Counter(['eggs', 'ham'])
>>> c['bacon']                              # count of a missing element is zero
0

设置一个计数为0不会从计数器中移去一个元素。使用 ​​del​​ 来删除它:

>>> c['sausage'] = 0                        # counter entry with a zero count
>>> del c['sausage']                        # del actually removes the entry

defaultdict

defaultdict是类似于字典的对象,它提供字典提供的所有方法,但将第一个参数(default_factory)作为字典的默认数据类型。使用defaultdict比使用dict.set_default方法执行相同操作更快。

>>> 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)
...
>>> d.items()
dict_items([('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])])

在该示例中,即使defaultdict对象中没有键,您也可以看到它会自动创建一个空列表。list.append然后有助于将值附加到列表中。

使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict:

>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1'] # key1存在
'abc'
>>> dd['key2'] # key2不存在,返回默认值
'N/A'

nametuple

命名元组有助于了解元组中每个位置的含义,并允许我们以更好的可读性和自记录代码进行编码。您可以在使用元组的任何地方使用它们。在示例中,我们将创建一个命名元组以显示点的保留信息。

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])  # Defining the namedtuple
>>> p = Point(10, y=20)  # Creating an object
>>> p
Point(x=10, y=20)
>>> p.x + p.y
30
>>> p[0] + p[1]  # Accessing the values in normal way
30
>>> x, y = p     # Unpacking the tuple
>>> x
10
>>> y
20

deque

deque就是我们数据结构中听说的双端队列,Python已经帮我实现了这个功能。

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])

deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。

# -*- coding: utf-8 -*-
"""
下面这个是一个有趣的例子,主要使用了deque的rotate方法来实现了一个无限循环
的加载动画
"""
import sys
import time
from collections import deque

fancy_loading = deque('>--------------------')

while True:
    print('\r%s' % ''.join(fancy_loading))
    fancy_loading.rotate(1)
    sys.stdout.flush()
    time.sleep(0.08)

# Result:

# 一个无尽循环的跑马灯
# ------------->-------

OrderedDict

顾名思义,有序字典。当我们使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

如果要保持 Key 的顺序,可以用 OrderedDict:

>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])

注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

>>> od = OrderedDict()
>>> od['z'] = 1
>>> od['y'] = 2
>>> od['x'] = 3
>>> od.keys() # 按照插入的Key的顺序返回
['z', 'y', 'x']

ChainMap

3.3 新版功能.

一个 ​​ChainMap​​​ 类是为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理。它通常比创建一个新字典和多次调用 ​​update()​​ 要快很多。

ChainMap可以把一组dict串起来并组成一个逻辑上的dict。ChainMap本身也是一个dict,但是查找的时候,会按照顺序在内部的dict依次查找。

一个 ChainMap 通过引用合并底层映射。 所以,如果一个底层映射更新了,这些更改会反映到 ChainMap 。

支持所有常用字典方法。另外还有一个 maps 属性(attribute),一个创建子上下文的方法(method), 一个存取它们首个映射的属性(property):

>>> baseline = {'music': 'bach', 'art': 'rembrandt'}
>>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}
>>> list(ChainMap(adjustments, baseline))
['music', 'art', 'opera']

什么时候使用ChainMap最合适?举个例子:应用程序往往都需要传入参数,参数可以通过命令行传入,可以通过环境变量传入,还可以有默认参数。我们可以用ChainMap实现参数的优先级查找,即先查命令行参数,如果没有传入,再查环境变量,如果没有,就使用默认参数。

总结

  • Counter: 计数器,主要用来计数
  • defaultdict: 带有默认值的字典
  • namedtuple(): 生成可以使用名字来访问元素内容的tuple子类
  • deque: 双端队列,可以快速的从另外一侧追加和推出对象
  • OrderedDict: 有序字典
  • ChainMap:多个映射快速的链接到一起


站在巨人的肩膀上:

  1. 官方文档-- ​​collections​​ — 容器数据类型
  2. 免费视频课–​​python必学模块-collections​
  3. 廖大神的官方网站–​​collections​
  4. 不可不知的Python模块: ​​collections​
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。