Python中的collections库是一个非常实用的工具库,是对基础数据结构的补充。
1) collections.Counter 用于计数
假设我们给定了一个字符串列表,需要计算列表中每个字符串的出现次数。
使用字典是一种基本方法:
但你知道吗,我们还可以使用 collections.Counter
来实现这一功能。
使用 collections.Counter
有以下好处:
无需处理字典逻辑
生成的代码非常易读
无需安装第三方库,因为
collections
是 Python 标准库的一部分
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()
,即一个空列表如果我们试图访问一个不存在的键,就会自动创建一个空列表作为默认值
此外,请注意代码更简短、更易读了
在生产级 Python 代码中,我还看到很多命名的元组。
命名元组是一种特殊的元组:
我们可以像访问普通元组一样访问值,例如:
mytuple[0], mytuple[1]
我们还可以像访问类一样访问值,例如
mytuple.name、 mytuple.age
在这里,我们创建了一个名为 Dog 的元组:
注意,我们可以像访问普通元组一样访问它的值,例如:
dog[0], dog[1], dog[2]
。我们还可以像访问对象一样访问它的值,例如
dog.name、dog.age、dog.breed
。
为什么我们在生产级 Python 代码中如此频繁地使用命名元组?
dog.name
比dog[0]
更易读,也更一目了然。但对于较小的对象,我们不想为此创建整个类的开销
因此,在这种情况下,命名元组可以在可读性和方便性之间取得平衡。
deque 是一个双端队列,从左右两端添加/删除项目都需要 O(1) 时间。
当我们在 Python 中实现队列时,没有经验的程序员可能会使用内置的 list。
注意,从列表左侧添加和删除需要 O(n) 时间,而不是 O(1) 时间。注意:O(1) 要比 O(n) 高效得多。
接下来,改用 deque。
现在,请注意所有 4 个操作都需要 O(1) 时间。
6) collections.abc
collections.abc
与 collections
略有不同。
collections.abc
包含抽象基类,如 Sequence、Mapping、Hashable 等。我们可以使用这些抽象基类来检查某个类是否提供了特定功能。
注意 collections
和 collections.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,用户就可以放心使用其他序列。
collections.abc.Mapping
是一个抽象基类,用于映射(即任何包含mapping的内容,如字典)。
注意 - typing.Mapping
只是从collections.abc.Mapping
导入
同样,在类型提示中,使用 Mapping 而不是 dict 或 DefaultDict 通常被认为是一种好的做法。
如果我们在类型提示中使用 Mapping 而不是 dict,该函数的用户就可以使用其他映射,如 defaultdict、mappingproxy 等,而不必担心林特或类型检查程序会抱怨。
9)collections.abc 中的其他抽象类
在生产级 Python 代码中,我可能用得最多的是 collections.abc.Sequence
和 collections.abc.Mapping
,但我还是会时不时地看到这些抽象类。
Hashable
可用于检查值是否可以散列。注意:只有哈希值才能成为字典键,或添加到集合中。
Callable
可以用来检查对象是否可以像函数一样被调用。
Crossin的新书《码上行动:用ChatGPT学会Python编程》已经上市了。 本书以ChatGPT为辅助,系统全面地讲解了如何掌握Python编程,适合Python零基础入门的读者学习。
购买后可加入读者交流群,Crossin为你开启陪读模式,解答你在阅读本书时的一切疑问。
Crossin的其他书籍:
添加微信 crossin123 ,加入编程教室共同学习 ~
感谢 转发 和 点赞 的各位~
热门跟贴