python collections 的超赞功能

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

图片



Crossin的新书《码上行动:用ChatGPT学会Python编程》已经上市了。本书以ChatGPT为辅助,系统全面地讲解了如何掌握Python编程,适合Python零基础入门的读者学习。【点此查看详细介绍】
Crossin的其他书籍:


图片

感谢转发点赞的各位~