Python中的collections库是一个非常实用的工具库,是对基础数据结构的补充。

1) collections.Counter 用于计数

假设我们给定了一个字符串列表,需要计算列表中每个字符串的出现次数。

使用字典是一种基本方法:

打开网易新闻 查看精彩图片

但你知道吗,我们还可以使用 collections.Counter 来实现这一功能。

打开网易新闻 查看精彩图片

使用 collections.Counter 有以下好处:

  • 无需处理字典逻辑

  • 生成的代码非常易读

  • 无需安装第三方库,因为 collections 是 Python 标准库的一部分

2) collections.OrderedDict

collections.OrderedDict 创建的字典可以保证键插入的顺序--在有序字典中,先插入的键会排在前面。

打开网易新闻 查看精彩图片

普通字典不也是这样吗? 差不多吧,但普通字典并不是为了保持这种顺序而建立的,因此可能无法保证其键的插入顺序。 ( 注: 从Python3.6开始,dict的插入顺序是保持的,同OrderedDict效果相同 )

3) collections.defaultdict

实际上,我经常在生产级 Python 代码中看到这种情况。

defaultdict 是一种特殊的字典,如果我们试图使用一个不存在的键,它会自动初始化一个默认的键值对。

打开网易新闻 查看精彩图片

注意到我们在defaultdict() 中输入了 int

  • defaultdict() 应该接收一个函数。

  • 该函数不带任何参数

  • 该函数返回的值就是 defaultdict 的默认值

  • defaultdict(int)中,默认值是 int(),也就是 0

  • 如果我们试图访问一个不存在的键,例如 dd[100],默认值就会自动创建,而不需要我们处理这个逻辑。

  • 如果我们试图访问一个已存在的键,它的行为就像一个普通的字典。

比方说,我们有一个域名列表,想按顶级域名(如“.com ”或“.net”)进行分组。我们先使用普通的字典。

打开网易新闻 查看精彩图片

注意,我们需要自己处理键值对的创建逻辑。

现在改用 defaultdict

打开网易新闻 查看精彩图片

注意,使用 defaultdict 后,如果某个键不存在,我们就不再需要手动创建键值对了。

  • defaultdict(list)中,默认值是 list(),即一个空列表

  • 如果我们试图访问一个不存在的键,就会自动创建一个空列表作为默认值

  • 此外,请注意代码更简短、更易读了

4) collections.namedtuple

在生产级 Python 代码中,我还看到很多命名的元组。

命名元组是一种特殊的元组:

  • 我们可以像访问普通元组一样访问值,例如: mytuple[0], mytuple[1]

  • 我们还可以像访问类一样访问值,例如 mytuple.name、 mytuple.age

打开网易新闻 查看精彩图片

在这里,我们创建了一个名为 Dog 的元组:

  • 注意,我们可以像访问普通元组一样访问它的值,例如: dog[0], dog[1], dog[2]

  • 我们还可以像访问对象一样访问它的值,例如 dog.name、dog.age、dog.breed

为什么我们在生产级 Python 代码中如此频繁地使用命名元组?

  • dog.namedog[0]更易读,也更一目了然。

  • 但对于较小的对象,我们不想为此创建整个类的开销

  • 因此,在这种情况下,命名元组可以在可读性和方便性之间取得平衡。

5) collections.deque

deque 是一个双端队列,从左右两端添加/删除项目都需要 O(1) 时间。

当我们在 Python 中实现队列时,没有经验的程序员可能会使用内置的 list。

打开网易新闻 查看精彩图片

注意,从列表左侧添加和删除需要 O(n) 时间,而不是 O(1) 时间。注意:O(1) 要比 O(n) 高效得多。

接下来,改用 deque。

打开网易新闻 查看精彩图片

现在,请注意所有 4 个操作都需要 O(1) 时间。

6) collections.abc

collections.abccollections 略有不同。

collections.abc 包含抽象基类,如 Sequence、Mapping、Hashable 等。我们可以使用这些抽象基类来检查某个类是否提供了特定功能

打开网易新闻 查看精彩图片

注意 collectionscollections.abc 模块包含不同的内容。

7) collections.abc.Sequence

collections.abc.Sequence是序列(如列表、元组、命名元组等)的基础抽象类。我们可以使用 issubclass() 方法来验证这一点:

打开网易新闻 查看精彩图片

注意 - collections.abc.Sequencetyping.Sequence 完全相同 - 事实上,typing 模块从 collections.abc 模块导入了 Sequence

打开网易新闻 查看精彩图片

我们经常在类型提示中使用 collections.abc.Sequence,而不是 list/tuple/等。这是因为函数输入参数类型提示的目的是更通用:

打开网易新闻 查看精彩图片

如果我们使用 list 而不是 Sequence 作为类型提示,用户在使用其他序列(如元组)时,可能会收到来自他们的线程或类型检查程序的投诉。

  • 如果我们使用Sequence而不是 list,用户就可以放心使用其他序列。

  • 8) collections.abc.Mapping

    collections.abc.Mapping是一个抽象基类,用于映射(即任何包含mapping的内容,如字典)。

    打开网易新闻 查看精彩图片

    注意 - typing.Mapping 只是从collections.abc.Mapping 导入

    打开网易新闻 查看精彩图片

    同样,在类型提示中,使用 Mapping 而不是 dict 或 DefaultDict 通常被认为是一种好的做法。

    打开网易新闻 查看精彩图片

    如果我们在类型提示中使用 Mapping 而不是 dict,该函数的用户就可以使用其他映射,如 defaultdict、mappingproxy 等,而不必担心林特或类型检查程序会抱怨。

    9)collections.abc 中的其他抽象类

    在生产级 Python 代码中,我可能用得最多的是 collections.abc.Sequencecollections.abc.Mapping,但我还是会时不时地看到这些抽象类。

    Hashable 可用于检查值是否可以散列。注意:只有哈希值才能成为字典键,或添加到集合中。

    打开网易新闻 查看精彩图片

    Callable 可以用来检查对象是否可以像函数一样被调用。

    打开网易新闻 查看精彩图片

    Crossin的新书《码上行动:用ChatGPT学会Python编程》已经上市了。 本书以ChatGPT为辅助,系统全面地讲解了如何掌握Python编程,适合Python零基础入门的读者学习。

    购买后可加入读者交流群,Crossin为你开启陪读模式,解答你在阅读本书时的一切疑问。

    Crossin的其他书籍:

    添加微信 crossin123 ,加入编程教室共同学习 ~

    打开网易新闻 查看精彩图片

    感谢 转发点赞 的各位~