6.3.1 集合

Python 提供了集合类型 set,用于表示大量数据的无序集合体。集合可以由各种数据组 成,数据之间没有次序,并且互不相同。可见,Python 集合基本上就是数学中所说的集合①。

集合类型的值有两种创建方式:一种是用一对花括号将多个用逗号分隔的数据括起来; 另一种是调用函数 set(),此函数可以将字符串、列表、元组等类型的数据转换成集合类型的 数据。不管用哪种方式创建集合值,在 Python 内部都是以 set([…])的形式表示的。注意,空 集只能用 set()来创建,而不能用字面值{}表示,因为 Python 将{}用于表示空字典(见 6.3.2 节)。

下面的会话过程演示了集合类型的值的创建。注意,集合中是不能有相同元素的,因此Python 在创建集合值的时候会自动删除掉重复的数据。

① 当然 Python 集合并不完全等同于数学中的集合,例如数学中的集合可能是无穷集。

  1. >>> {1,2,3}
  2. set([1, 2, 3])
  3. >>> s = {1,1,2,2,2,3,3}
  4. >>> s
  5. set([1, 2, 3])
  6. >>> set('set')
  7. set(['s', 'e', 't'])
  8. >>> set('sets')
  9. set(['s', 'e', 't'])
  10. >>> set([1,1,1,2,1])
  11. set([1, 2])
  12. >>> set((1,2,1,1,2,3,4))
  13. set([1, 2, 3, 4])
  14. >>> set()
  15. set([])
  16. >>> type(set())
  17. <type 'set'>
  18. >>> type({})
  19. <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 集合运算

下面是集合运算的例子:

  1. >>> s1 = {1,2,3,4,5}
  2. >>> s2 = {2,4,6,8}
  3. >>> 6 in s1
  4. False
  5. >>> 6 in s2
  6. True
  7. >>> s1 | s2
  8. set([1, 2, 3, 4, 5, 6, 8])
  9. >>> s1 & s2
  10. set([2, 4])
  11. >>> s1 - s2
  12. set([1, 3, 5])
  13. >>> s1 |= s2
  14. >>> s1
  15. set([1, 2, 3, 4, 5, 6, 8])
  16. >>> len(s2)
  17. 4

和序列一样,集合与 for 循环语句结合使用,可实现对集合中每个元素的遍历。例如, 接着上面的例子继续执行语句:

  1. >>> for x in s2:
  2. print x,
  3. 8 2 4 6

Python 集合是可修改的数据类型,例如上面例子中修改了集合 s1 的值。但是,Python 集合中的元素必须是不可修改的!因此,集合的元素不能是列表、字典等,只能是数值、字 符串、元组之类。同样,集合的元素不能是集合,因为集合是可修改的。然而,Python 另 外提供了 frozenset()函数,可用来创建不可修改的集合,这种集合可以作为另一个集合的元 素。下面的语句展示了 set 和 frozenset 的区别:

  1. >>> a = set(['hi','there'])
  2. >>> b = set([a,3])
  3. Traceback (most recent call last):
  4. File "&lt;pyshell#74&gt;", line 1, in &lt;module&gt; b = set([a,3])
  5. TypeError: unhashable type: 'set'
  6. >>> a = frozenset(['hi','there'])
  7. >>> b = set([a,3])
  8. >>> b
  9. 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 集合对象的方法

接着前面的例子,下面通过集合对象方法的调用来处理集合数据:

  1. >>> s2.union([1,2,3])
  2. set([1, 2, 3, 4, 6, 8])
  3. >>> s2.intersection((1,2,3,4))
  4. set([2, 4])
  5. >>> set([2,4]).issubset(s2)
  6. True
  7. >>> s2.issuperset(set([2,4]))
  8. True
  9. >>> s2.add(10)
  10. >>> s2
  11. set([8, 2, 4, 10, 6])
  12. >>> print s2.pop()
  13. 8
  14. >>> s2
  15. set([2, 4, 10, 6])