|
|
|
|
移动端

2.1.2 集合类型(3)

《Python高级编程(第2版)》第2章语法最佳实践——类级别以下,本章将介绍现在这门语言的语法中最重要的元素,以及它们的使用技巧。本节为大家介绍集合类型。

作者:张亮/阿信 译来源:人民邮电出版社|2018-01-29 18:21

技术沙龙 | 6月30日与多位专家探讨技术高速发展下如何应对运维新挑战!


2.1.2 集合类型(3)

如上述代码所示,字典元素的顺序既与对象的散列方法无关,也与元素的添加顺序无关。但我们也不能完全信赖这一说法,因为在不同的Python实现中可能会有所不同。

但在某些情况下,开发者可能需要使用能够保存添加顺序的字典。幸运的是,Python标准库的collections模块提供了名为OrderedDict的有序字典。它选择性地接受一个可迭代对象作为初始化参数:

  1. >>> from collections import OrderedDict  
  2. >>> OrderedDict((str(number), None) for number in range(5)).keys()  
  3. odict_keys(['0', '1', '2', '3', '4']) 

OrderedDict还有一些其他功能,例如利用popitem()方法在双端取出元素或者利用move _ to _ end()方法将指定元素移动到某一端。这种集合类型的完整参考可参见Python文档(https://docs.python.org/3/library/collections.html)。

还有很重要的一点是,在非常老的代码库中,可能会用dict来实现原始的集合,以确保元素的唯一性。虽然这种方法可以给出正确的结果,但只有在低于2.3的Python版本中才予以考虑。字典的这种用法十分浪费资源。Python有内置的set类型专门用于这个目的。事实上,CPython中set的内部实现与字典非常类似,但还提供了一些其他功能,以及与集合相关的特定优化。

3.集合

集合是一种鲁棒性很好的数据结构,当元素顺序的重要性不如元素的唯一性和测试元素是否包含在集合中的效率时,大部分情况下这种数据结构是很有用的。它与数学上的集合概念非常类似。Python的内置集合类型有两种。

set():一种可变的、无序的、有限的集合,其元素是唯一的、不可变的(可哈希的)对象。

frozenset():一种不可变的、可哈希的、无序的集合,其元素是唯一的、不可变的(可哈希的)对象。

由于frozenset()具有不变性,它可以用作字典的键,也可以作为其他set()和frozenset()的元素。在一个set()或frozenset()中不能包含另一个普通的可变set(),因为这会引发TypeError:

  1. >>> set([set([1,2,3]), set([2,3,4])])  
  2. Traceback (most recent call last):  
  3.   File "< stdin >", line 1, in < module > 
  4. TypeError: unhashable type: 'set' 

下面这种集合初始化的方法是完全正确的:

  1. >>> set([frozenset([1,2,3]), frozenset([2,3,4])])  
  2. {frozenset({1, 2, 3}), frozenset({2, 3, 4})}  
  3. >>> frozenset([frozenset([1,2,3]), frozenset([2,3,4])])  
  4. frozenset({frozenset({1, 2, 3}), frozenset({2, 3, 4})}) 

创建可变集合方法有以下3种,如下所示。

调用set(),选择性地接受可迭代对象作为初始化参数,例如set([0, 1, 2])。

使用集合推导,例如{element for element in range(3)}。

使用集合字面值,例如{1, 2, 3}。
注意,使用集合的字面值和推导要格外小心,因为它们在形式上与字典的字面值和推导非常相似。此外,空的集合对象是没有字面值的。空的花括号{}表示的是空的字典字面值。

实现细节

CPython中的集合与字典非常相似。事实上,集合被实现为带有空值的字典,只有键才是实际的集合元素。此外,集合还利用这种没有值的映射做了其他优化。

由于这一点,可以快速向集合添加元素、删除元素或检查元素是否存在,平均时间复杂度均为O(1)。但由于CPython的集合实现依赖于类似的散列表结构,因此这些操作的最坏情况复杂度是O(n),其中n是集合的当前大小。

字典的其他实现细节也适用于集合。集合中的元素必须是可哈希的,如果集合中用户自定义类的实例的散列方法不佳,那么将会对性能产生负面影响。

4.超越基础集合类型——collections模块

每种数据结构都有其缺点。没有一种集合类型适合解决所有问题,4种基本类型(元组、列表、集合和字典)提供的选择也不算多。它们是最基本也是最重要的集合类型,都有专门的语法。幸运的是,Python标准库内置的collections模块提供了更多的选择。前面已经提到过其中一种(deque)。下面是这个模块中最重要的集合类型。

namedtuple():用于创建元组子类的工厂函数(factory function),可以通过属性名来访问它的元索引。

deque:双端队列,类似列表,是栈和队列的一般化,可以在两端快速添加或取出元素。

ChainMap:类似字典的类,用于创建多个映射的单一视图。

Counter:字典子类,由于对可哈希对象进行计数。

OrderedDict:字典子类,可以保存元素的添加顺序。

defaultdict:字典子类,可以通过调用用户自定义的工厂函数来设置缺失值。
  
第12章介绍了从collections模块选择集合类型的更多细节,也给出了关于何时使用这些集合类型的建议。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

程序设计实践双语版

程序设计实践并不只是写代码。程序员必须评论各种折衷方案,在许多可能性之中做出选择、排除错误、做测试和改进程序性能,还要维护自己或其...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊