集合(set)
(1)集合的元素
(2)集合的构造
(3)集合的操作**
写在前面:

集合的概念来源于数学,因此,python的集合同样支持元素的判断,也支持各种重要的集合操作,并集、交集、差集等。
表达式:{元素,…}
空集合:set{}(注意:这里不能直接使用{},{}表示的是空字典)
python由两个表示集合的类型:set 和 frozenset(冻结集合)。两者的不同之处在于set是可变类型,而frozenset是不变类型。
要生成frozenset的对象,只能用frozenset(…)的形式。
接下来主要介绍set,与元素变动无关的均适用于frozenset。

集合的元素
集合的元素只能是不变对象,而且必须能做相等比较(用 == 运算符)。内置的数值类型、字符串、bool对象,及他们的元组等都满足这些要求。
元素对象具有唯一性,不会出现重复元素,元素之间也没有顺序关系。
e.g.

{6,6,2,2,7,7,4,4,5,5}
{2,4,5,6,7}
1
2
集合的构造
直接描述
e.g.

{‘math’, ‘Math’, ‘MATH’, ‘phys’, ‘Phys’}
{‘phys’, ‘MATH’, ‘math’, ‘Phys’, ‘Math’}

注意:元素的排列是不能控制的

set(…)转换
从任意的序列或可迭代对象生成相应的集合
e.g.

set([3,7,5,4,9])
{3, 4, 5, 7, 9}

用描述式生成集合
{生成器表达式}
e.g.

s = {x for x in range(5)}
{0, 1, 2, 3, 4}

类型转换
tuple
如果一个tuple的元素总能用 == 比较,就可以从它转换得到一个set对象,但顺序丢失,重复元素消去。另一方面,一个set对象总能转换得到一个tuple对象。
list
如果一个list里的元素都满足set对元素的要求,就可以从这个list转换得到一个set对象,但表对象的顺序丢失,消除了重复元素。另一方面,一个set对象,总能转换得到一个表对象。
字符串
任何字符串可以转换得到一个集合,其中的元素就是原字符串中单个字符的串,消去重复字符,顺序内定。从集合转换得到字符串得到集合的字符串表示,意思完全不同。

特殊状况

set() is set()
False #两次生成的空集合(set)不是同一个对象

frozenset() is frozenset()
True #不会创建两个不同的不变空集

{1, 1.0} #python认为数值1与1.0等值
{1.0}

{1.0, 1}
{1}

{1, True} #python认为True和1等值,False和0等值
{True}

{False, 0}
{0}
1
集合的操作
标准操作

序列 表达式 意义
1 len(s) 求集合长度,即集合内元素个数
2 x in s ; x not in s 判断x是否在集合s内,是返回True,否则返回False;not in 反之
3 for x in s: …x… 集合可作为可迭代对象使用,取得元素顺序由集合内部实现确定
4 sorted(s) 得到集合元素排序的表
简单实例

#len(s)

s = {1,2,3,4,5,6,7,8,9}
len(s)
9

#x in s ; x not in s

s = {1,2,3,4,5}
3 in s
True

9 in s
False

#for x in s: …x…

s = {2,7,1,‘a’,‘s’,‘d’}
for x in s:
print(x)

#sorted(s)

s = {1,5,7,2,4,5}
sorted(s)
[1, 2, 4, 5, 7]

s = {‘a’,‘d’,‘z’,‘y’,‘m’}
sorted(s)
[‘a’, ‘d’, ‘m’, ‘y’, ‘z’]

#调用sorted(s)时,s里不能同时用str和int,否则会报错

s = {1,3,‘a’,‘d’}
sorted(s)
Traceback (most recent call last):
File “<pyshell#28>”, line 1, in
sorted(s)
TypeError: ‘<’ not supported between instances of ‘int’ and ‘str’

集合的比较

序列 表达式 意义
1 s1 <= s2 ; s1.issubset(s2) 当且仅当s1为s2子集时返回True
2 s1 < s2 当且仅当s1为s2的真子集时得到True;真子集说明s2至少包含一个不属于s1的元素
3 s1 > = s2 ; s1.issuperset(s2) 判断s1是否为s2的超集
4 s1 > s2 判断s1是否为s2的真超集
5 s1.isdisjoint(s2) 判断两个集合是否不想交,即有没有公共元素
简单实例

s1 = {1,2,3,4,5,6,7,8,9,10}
s2 = {2,4,6,8,10}

s1 <= s2
False

s1 < s2
False

s1 >= s2
True

s1 > s2
True

s1.isdisjoint(s2)
False

集合运算

序列 表达式 意义
1 s1.union(s2, …) ; s1/ s2(直线) 并集,生成新集合
2 s1.intersection(s2, …) ; s1 & s2 & … 交集,生成新集合
3 s1.difference(s2, …) ; s1 -s2 - … 生成第一个集合减去后面集合的差集
4 s1.symmetric_difference(s2) 生成s1和s2的对称差集,包含属于s1但不属于s2,属于s2但不属于s1(即并集与交集的差集)
5 s1.copy() 生成s1的拷贝
简单实例

s1 = {1,2,3,4,5,6,7,8,9,10}
s2 = {2,4,6,8,10,12,14,16}

s1 | s2 #表格里因无法输入 | 显示的是 \ ,正确使用时应用 |
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16}

s1 & s2
{2, 4, 6, 8, 10}

s1 - s2
{1, 3, 5, 7, 9}

s1.symmetric_difference(s2)
{1, 3, 5, 7, 9, 12, 14, 16}

s1.copy()
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

tip: 对于非运算符形式的集合运算,比如s.union(…),其实参可以是任意可迭代对象。采用运算符的形式时参数必须是集合。

修改集合

序列 表达式 意义
1 s.add(x) 将元素x加入集合s
2 s.remove(x) 从s里删除元素x,若s里无x报错
3 s.discard(x) 如果s里有x,抛弃,若无则什么都不做
4 s.pop() 从s里删除某个(任意的)元素并返回它,具体元素由集合内部确定。若s空,将报错
5 s.clear() 清除s里的所有元素
简单实例

s = {1,7,9,‘c’,‘e’,5,‘s’}
#s随操作不断更新

s.add(2)
s
{1, 2, ‘s’, 5, ‘e’, 7, 9, ‘c’}

s.remove(‘c’)
s
{1, 2, ‘s’, 5, ‘e’, 7, 9}

s.discard(1)
s
{2, ‘s’, 5, ‘e’, 7, 9}

s.pop()
2

s
{‘s’, 5, ‘e’, 7, 9}

s.clear()
s
set()

集合更新操作

序列 表达式 意义
1 s1.update(s2, …) ; s1 /=s2 /…(直线) 修改s1,使之包含属于其他集合的元素
2 s1.intersection_update(s2, …) ; s1 &= s2 & … 修改s1,使之只包含同属所有集合的公共元素
3 s1.differnence_update(s2, …) ; s1 -=s2 / … 修改s1,从中去除属于其他集合的元素
4 s1.symmetric_difference_update(s2) 修改s1,使之只包含仅属于s1或s2之一但不同时属于两者的元素
简单实例

s1 = {1,2,3,4,5,6,7,8,9,10}
s2 = {2,4,6,8,10,12,14,16}

s1 |= s2
s1
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16}

s1 &= s2
s1
{2, 4, 6, 8, 10, 12, 14, 16}

s1 -= s2
s1
set()

s1.symmetric_difference_update(s2)
{2, 4, 6, 8, 10, 12, 14, 16}