Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2856923
  • 博文数量: 471
  • 博客积分: 7081
  • 博客等级: 少将
  • 技术积分: 5369
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-04 21:55
文章分类

全部博文(471)

文章存档

2014年(90)

2013年(69)

2012年(312)

分类: Python/Ruby

2013-02-27 14:01:47

集合

集合set 是装有独特值的无序“袋子”。一个简单的集合可以包含任何数据类型的值。如果有两个集合,则可以执行像联合、交集以及集合求差等标准集合运算。

创建集合

重中之重。创建集合非常简单。

[] []
>>> a_set = {1} >>> a_set {1} >>> type(a_set) 'set'> >>> a_set = {1, 2} >>> a_set {1, 2}
要创建只包含一个值的集合,仅需将该值放置于花括号之间。({})。
实际上,集合以 的形式实现,但目前还无须考虑这一点。
要创建多值集合,请将值用逗号分开,并用花括号将所有值包裹起来。

还可以 为基础创建集合。

[] []
>>> a_list = ['a', 'b', 'mpilgrim', True, False, 42] >>> a_set = set(a_list) >>> a_set {'a', False, 'b', True, 'mpilgrim', 42} >>> a_list ['a', 'b', 'mpilgrim', True, False, 42]
要从列表创建集合,可使用 set() 函数。(懂得如何实现集合的学究可能指出这实际上并不是调用某个函数,而是对某个类进行实例化。我保证在本书稍后的地方将会学到其中的区别。目前而言,仅需知道 set() 行为与函数类似,以及它返回一个集合。)
正如我之前提到的,简单的集合可以包括任何数据类型的值。而且,如我之前所提到的,集合是 无序的。该集合并不记得用于创建它的列表中元素的最初顺序。如果向集合中添加元素,它也不会记得添加的顺序。
初始的列表并不会发生变化。

还没有任何值?没有问题。可以创建一个空的集合。

[] []
要创建空集合,可不带参数调用 set() 。
打印出来的空集合表现形式看起来有点儿怪。也许,您期望看到一个 {} 吧 ?该符号表示一个空的字典,而不是一个空的集合。本章稍后您将学到关于字典的内容。
尽管打印出的形式奇怪,这 确实是 一个集合……
…… 同时该集合没有任何成员。
由于从 Python 2 沿袭而来历史的古怪规定,不能使用两个花括号来创建空集合。该操作实际创建一个空字典,而不是一个空集合。

修改集合

有两种方法可向现有集合中添加值: add() 方法和 update() 方法。

[] []
>>> a_set = {1, 2} >>> a_set.add(4) >>> a_set {1, 2, 4} >>> len(a_set) 3 >>> a_set.add(1) >>> a_set {1, 2, 4} 3
add() 方法接受单个可以是任何数据类型的参数,并将该值添加到集合之中。
该集合现在有三个成员了。
集合是装 唯一值 的袋子。如果试图添加一个集合中已有的值,将不会发生任何事情。将不会引发一个错误;只是一条空操作。
该集合 仍然 只有三个成员。

[] []
>>> a_set = {1, 2, 3} >>> a_set {1, 2, 3} >>> a_set.update({2, 4, 6}) >>> a_set {1, 2, 3, 4, 6} >>> a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13}) >>> a_set {1, 2, 3, 4, 5, 6, 8, 9, 13} >>> a_set.update([10, 20, 30]) >>> a_set {1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
update() 方法仅接受一个集合作为参数,并将其所有成员添加到初始列表中。其行为方式就像是对参数集合中的每个成员调用 add() 方法。
由于集合不能包含重复的值,因此重复的值将会被忽略。
实际上,可以带任何数量的参数调用 update() 方法。如果调用时传递了两个集合, update() 将会被每个集合中的每个成员添加到初始的集合当中(丢弃重复值)。
update() 方法还可接受一些其它数据类型的对象作为参数,包括列表。如果调用时传入列表,update() 将会把列表中所有的元素添加到初始集合中。

从集合中删除元素

有三种方法可以用来从集合中删除某个值。前两种,discard() 和 remove() 有细微的差异。

[] []
>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45} >>> a_set {1, 3, 36, 6, 10, 45, 15, 21, 28} >>> a_set.discard(10) >>> a_set {1, 3, 36, 6, 45, 15, 21, 28} >>> a_set.discard(10) >>> a_set {1, 3, 36, 6, 45, 15, 21, 28} >>> a_set.remove(21) >>> a_set {1, 3, 36, 6, 45, 15, 28} >>> a_set.remove(21) Traceback (most recent call last): File "", line 1, in KeyError: 21
discard() 接受一个单值作为参数,并从集合中删除该值。
如果针对一个集合中不存在的值调用 discard() 方法,它不进行任何操作。不产生错误;只是一条空指令。
remove() 方法也接受一个单值作为参数,也从集合中将其删除。
区别在这里:如果该值不在集合中,remove() 方法引发一个 KeyError 例外。

就像列表,集合也有个 pop() 方法。

[] []
>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45} >>> a_set.pop() 1 >>> a_set.pop() 3 >>> a_set.pop() 36 >>> a_set {6, 10, 45, 15, 21, 28} >>> a_set.clear() >>> a_set set() >>> a_set.pop() Traceback (most recent call last): File "", line 1, in KeyError: 'pop from an empty set'
pop() 方法从集合中删除某个值,并返回该值。然而,由于集合是无序的,并没有“最后一个”值的概念,因此无法控制删除的是哪一个值。它基本上是随机的。
clear() 方法删除集合中 所有 的值,留下一个空集合。它等价于 a_set = set(),该语句创建一个新的空集合,并用之覆盖 a_set 变量的之前的值。
试图从空集合中弹出某值将会引发 KeyError 例外。

常见集合操作

Python 的 集合 类型支持几种常见的运算。

[] []
>>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195} >>> 30 in a_set True >>> 31 in a_set False >>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21} >>> a_set.union(b_set) {1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127} >>> a_set.intersection(b_set) {9, 2, 12, 5, 21} >>> a_set.difference(b_set) {195, 4, 76, 51, 30, 127} >>> a_set.symmetric_difference(b_set) {1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}
要检测某值是否是集合的成员,可使用 in 运算符。其工作原理和列表的一样。
union() 方法返回一个新集合,其中装着 在两个 集合中出现的元素。
intersection() 方法返回一个新集合,其中装着 同时 在两个集合中出现的所有元素。
difference() 方法返回的新集合中,装着所有在 a_set 出现但未在 b_set 中的元素。
symmetric_difference() 方法返回一个新集合,其中装着所有 只在其中一个 集合中出现的元素。

这三种方法是对称的。

[] []
a_set 与 b_set 的对称差分 看起来 和b_set 与 a_set 的对称差分不同,但请记住:集合是无序的。任何两个包含所有同样值(无一遗漏)的集合可认为是相等的。
而这正是这里发生的事情。不要被 Python Shell 对这些集合的输出形式所愚弄了。它们包含相同的值,因此是相等的。
对两个集合的 Union[并集]操作也是对称的。
对两个集合的 Intersection[交集]操作也是对称的。
对两个集合的 Difference[求差]操作不是对称的。这是有意义的;它类似于从一个数中减去另一个数。操作数的顺序会导致结果不同。

最后,有几个您可能会问到的问题。

[] []
>>> a_set = {1, 2, 3} >>> b_set = {1, 2, 3, 4} >>> a_set.issubset(b_set) True >>> b_set.issuperset(a_set) True >>> a_set.add(5) >>> a_set.issubset(b_set) False >>> b_set.issuperset(a_set) False
a_set 是 b_set 的 子集 — 所有 a_set 的成员均为 b_set 的成员。
同样的问题反过来说, b_set 是 a_set 的 超集,因为 a_set 的所有成员均为 b_set 的成员。
一旦向 a_set 添加一个未在 b_set 中出现的值,两项测试均返回 False 。

布尔上下文环境中的集合

可在 if 这样的 使用集合。

[] []
>>> def is_it_true(anything): ...   if anything: ...     print("yes, it's true") ...   else: ...     print("no, it's false") ... >>> is_it_true(set()) no, it's false >>> is_it_true({'a'}) yes, it's true >>> is_it_true({False}) yes, it's true
在布尔类型上下文环境中,空集合为假值。
任何至少包含一个上元素的集合为真值。
任何至少包含一个上元素的集合为真值。元素的值无关紧要。
阅读(7910) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~