python collections 的超赞功能

liftword2周前 (06-03)技术文章3

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.Sequence typing.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 可以用来检查对象是否可以像函数一样被调用。

相关文章

python面向对象四大支柱——抽象(Abstraction)详解

抽象是面向对象编程的四大支柱之一,它强调隐藏复杂的实现细节,只暴露必要的接口给使用者。下面我将全面深入地讲解Python中的抽象概念及其实现方式。一、抽象的基本概念1. 什么是抽象?抽象是一种"...

探秘Python抽象类

在那篇探讨Python接口与“鸭类型”关系的文章中(Python中接口与鸭类型),我们详细介绍了Python中接口的实现方式--鸭类型。尽管“鸭类型”仅作为接口的一种实现策略,并不具备像Java等其他...

[python] python抽象基类使用总结

在Python中,抽象基类是一类特殊的类,它不能被实例化,主要用于作为基类被其他子类继承。抽象基类的核心作用是为一组相关的子类提供统一的蓝图或接口规范,明确规定子类必须实现的方法,从而增强代码的规范性...

Python面向对象编程(OOP)实践教程

一、OOP理论基础1. 面向对象编程概述面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,它使用"对象"来设计应用程序和软件。OOP的核心...

抽象基类ABC,名字取的傻白甜,其实是Python进阶必会知识点

作者:麦叔来源:麦叔编程ABC是什么我们来聊一个Python进阶话题,抽象基类,英文是Abstract Base Class,简称为ABC。这个名字看起来很简单,ABC,但其实是Python进阶的重要...

编程开发中的抽象概念

在编程开发中,抽象概念是核心思想之一,它通过隐藏复杂细节、提炼共性模式来简化设计和实现。以下是编程中常见的抽象概念分类及示例:1. 数据抽象(Data Abstraction)核心思想:将数据的具体表...