6.3.1 集合
Python 提供了集合类型 set,用于表示大量数据的无序集合体。集合可以由各种数据组 成,数据之间没有次序,并且互不相同。可见,Python 集合基本上就是数学中所说的集合①。
集合类型的值有两种创建方式:一种是用一对花括号将多个用逗号分隔的数据括起来; 另一种是调用函数 set(),此函数可以将字符串、列表、元组等类型的数据转换成集合类型的 数据。不管用哪种方式创建集合值,在 Python 内部都是以 set([…])的形式表示的。注意,空 集只能用 set()来创建,而不能用字面值{}表示,因为 Python 将{}用于表示空字典(见 6.3.2 节)。
下面的会话过程演示了集合类型的值的创建。注意,集合中是不能有相同元素的,因此Python 在创建集合值的时候会自动删除掉重复的数据。
① 当然 Python 集合并不完全等同于数学中的集合,例如数学中的集合可能是无穷集。
>>> {1,2,3}
set([1, 2, 3])
>>> s = {1,1,2,2,2,3,3}
>>> s
set([1, 2, 3])
>>> set('set')
set(['s', 'e', 't'])
>>> set('sets')
set(['s', 'e', 't'])
>>> set([1,1,1,2,1])
set([1, 2])
>>> set((1,2,1,1,2,3,4))
set([1, 2, 3, 4])
>>> set()
set([])
>>> type(set())
<type 'set'>
>>> type({})
<type 'dict'>
集合类型支持多种运算,学过中学数学的读者很容易理解这些运算的含义。我们将常用 的集合运算列在表 6.6 中。
运算 | 含义 |
---|---|
x in <集合> | 检测 x 是否属于<集合>,返回 True 或 False |
s1 | s2 | 并集 |
s1 & s2 | 交集 |
s1 – s2 | 差集 |
s1 ^ s2 | 对称差 |
s1 <= s2 | 检测 s1 是否 s2 的子集 |
s1 < s2 | 检测 s1 是否 s2 的真子集 |
s1 >= s2 | 检测 s1 是否 s2 的超集 |
s1 > s2 | 检测 s1 是否 s2 的真超集 |
s1 |= s2 | 将 s2 的元素并入 s1 中 |
len(s) | s 中的元素个数 |
图 6.6 集合运算
下面是集合运算的例子:
>>> s1 = {1,2,3,4,5}
>>> s2 = {2,4,6,8}
>>> 6 in s1
False
>>> 6 in s2
True
>>> s1 | s2
set([1, 2, 3, 4, 5, 6, 8])
>>> s1 & s2
set([2, 4])
>>> s1 - s2
set([1, 3, 5])
>>> s1 |= s2
>>> s1
set([1, 2, 3, 4, 5, 6, 8])
>>> len(s2)
4
和序列一样,集合与 for 循环语句结合使用,可实现对集合中每个元素的遍历。例如, 接着上面的例子继续执行语句:
>>> for x in s2:
print x,
8 2 4 6
Python 集合是可修改的数据类型,例如上面例子中修改了集合 s1 的值。但是,Python 集合中的元素必须是不可修改的!因此,集合的元素不能是列表、字典等,只能是数值、字 符串、元组之类。同样,集合的元素不能是集合,因为集合是可修改的。然而,Python 另 外提供了 frozenset()函数,可用来创建不可修改的集合,这种集合可以作为另一个集合的元 素。下面的语句展示了 set 和 frozenset 的区别:
>>> a = set(['hi','there'])
>>> b = set([a,3])
Traceback (most recent call last):
File "<pyshell#74>", line 1, in <module> b = set([a,3])
TypeError: unhashable type: 'set'
>>> a = frozenset(['hi','there'])
>>> b = set([a,3])
>>> b
set([3, frozenset(['there', 'hi'])])
Python 以面向对象方式实现集合类型,集合对象的方法如表 6.7 所示。
方法 | 含义 |
---|---|
s1.union(s2) | 即 s1 | s2 |
s1.intersection(s2) | 即 s1 & s2 |
s1.difference(s2) | 即 s1 – s2 |
s1.symmetric_difference(s2) | 即 s1 ^ s2 |
s1.issubset(s2) | 即 s1 <= s2 |
s1.issuperset(s2) | 即 s1 >= s2 |
s1.update(s2) | s1 |= s2 |
s.add(x) | 向 s 中增加元素 x |
s.remove(x) | 从 s 中删除元素 x(无 x 则出错) |
s.discard(x) | 从 s 中删除元素 x(无 x 也不出错) |
s.pop() | 从 s 中删除并返回任一元素 |
s.clear() | 从 s 中删除所有元素 |
s.copy() | 复制 s |
表 6.7 集合对象的方法
接着前面的例子,下面通过集合对象方法的调用来处理集合数据:
>>> s2.union([1,2,3])
set([1, 2, 3, 4, 6, 8])
>>> s2.intersection((1,2,3,4))
set([2, 4])
>>> set([2,4]).issubset(s2)
True
>>> s2.issuperset(set([2,4]))
True
>>> s2.add(10)
>>> s2
set([8, 2, 4, 10, 6])
>>> print s2.pop()
8
>>> s2
set([2, 4, 10, 6])