集合类型其实就是一组数据构成的整体,Python中,集合类型被作为跟数组,字典一样的内建类型存在。一种比较标准的解释是:“集合对象是一种无序排列的可哈希的值”。字典的讲解中,我们也提到了可哈希的概念,这里也是一样,换句话说,集合中的元素跟字典的键一样,都是由原子型数据(就是数字,字符串,元组这些不可变数据类型)构成的。而且,集合中的元素跟字典还有一点一样,那就是他们都是唯一的(集合中不会出现多个一模一样的元素)。
集合的创建
先来看看如何创建一种集合类型。和列表,字符串这些类型一样,集合的创建方法也是两种: 直接赋值和 set() 函数
a = set("aabbc") # >>> {'a','b','c'}
b = {1,1,2} # >>> {1,2}
集合中的元素是唯一的,没有重复。所以,当我们把字符串 "aabbc" 传入 set() 函数的时候,集合中只有 'a','c' 三个元素,同理,b = {1,2} 的结果也只是 {1,2}。
需要注意的是,空集合只能用 set() 表示,因为 {} 会被认为是空字典。
集合的访问
集合与字典一样,没有下标,那么,也就不能通过索引或者切片访问了。集合中的元素也没有固定的顺序。如果我们要查看集合中的元素,可以通过for循环遍历
a = {1,2,3}
for i in a:
print(i) # >>> 依次输出1,3
集合的更新
1. 添加
a = {1,3}
a.add(4) # >>> {1,3,4}
用 add() 函数实现向集合中添加元素,当然,如果添加的元素在集合中已经存在,那么也就添加不进去了,因为本来集合的特性就是元素的唯一性
a = {1,3}
a.add(3) # >>> {1,3}
2. 删除
(1) remove()
a = {1,3}
a.remove(1) # >>> {2,3}
# 删除本就不存在于集合中的元素,会报错
a.remove(4) # 报错
(2) pop()
列表中,pop() 的作用是删除列表末尾的一个元素并返回这个删除的元素。但是在集合中,因为集合的元素是没有顺序的,所以集合中的pop() 会删除任意的元素,并返回
a = {1,3}
# pop()函数删除元素的顺序是任意的
a.pop() # >>> 1
a.pop() # >>> 2
a.pop() # >>> 3
a.pop() # 此时删除空集合,会报错
3. 拓展
(1) update()
该函数实现的功能为将两个集合合并
a = {1,3}
b = {1,4}
a.update(b)
print(a) # >>> {1,4}
print(b) # >>> {1,4}
需要强调的一点是,集合是可变类型,这个例子中,集合a的地址并没有发生变化
操作符
1. 标准类型
(1) 成员操作符 in,not in
和列表,字符串等类型一样的用法,判断元素是否属于一个集合
a = {1,3}
print(1 in a) # >>> True
print(4 not in a) # >>> False
(2) 等价操作符 ==,!=
两个集合等价是指:两个集合互相满足,一个集合的所有元素同时也是另一个集合的元素。也就是说两个集合的所有元素都一样。
a = {1,3}
print(a == b) # True
a.add(4)
print(a != b) # True
(3) 子集,超集 ,>=
如果集合A的所有元素都在集合B内,称A是B的子集,反过来,称B是A的超集。而如果B的所有元素并不是都在A内,则称A是B的严格子集(数学上我们也叫真子集),严格超集的概念同理,我就不写了
a = {1,3}
c = {1,4}
# c是a的严格超集
print(c > a) # >>> True
# b是c的严格子集
print(b < c) # >>> True
# a实际上与b等价,护卫非严格子集(超集)
print(a >= b and b >= a) # >>> True
2. 集合类型
(1) 联合: |,union()
其实是对集合求并,我们上面说过对集合的拓展,用的是 update() 函数,联合的作用跟上面说的拓展实际上是一样的。但是由一点有本质区别,update() 函数是对集合本身改变,而联合的两种方法:| 操作符以及 union() 函数都是通过生成新对象来保存合并的结果的
a = {1,4}
# “自并”操作
a |= b
print(a) # >>> {1,4}
c = {2,5}
# 将a和c合并的结果引用为d
d = a.union(c)
print(d) # >>> {1,4,5}
print(a) # >>> {1,4}
(2) 交集: &,intersection()
a = {1,3}
b = {2,3}
print(a & b) # >>> {2,3}
d = {1,5}
print(c.intersection(d)) # >>> {1,2}
# 道理和上面的联合一样,新对象保存结果,原对象不变
print(a) # >>> {1,3}
print(c) # >>> {1,3}
(3) 相对补集:-,difference()
集合A,B的相对补集是指只属于A而不属于B的元素构成的集合,用法跟上面的两个例子一样
a = {1,3}
print(a - b) # >>> {1}
c = {1,5}
print(d.difference(c)) # >>> {4,5}
(4) 对称差分:^,symmetric_difference()
看符号就知道跟异或是一个道理,返回值是两个集合中不同时在两个集合中出现的元素
a = {1,4}
print(a ^ b) # >>> {1,4}
c = {1,3}
print(c.symmetric_difference(d)) # >>> set()
内建函数
上面已经介绍过一些内建函数了,比如 add(),union(),intersection(),difference(),symmetric_difference(),update() 等,下面我再介绍几个有代表性的,更多的函数大家自己可以查阅相关文档。
1. 长度
“万能函数”len()
a = {1,2}
print(len(a)) # >>> 2
2. 判断子集和超集
s.issubset(t):s是t的子集,返回True,否则返回False
s.issuperset(t):s是t的超集,返回True,否则返回False
a = {1,2}
print(a.issubset(b)) # >>> False
print(a.issuperset(b)) # >>> True
3. “自变”函数
像函数 union(),difference() 这些函数都是生成了新的对象,而并没有改变对象自身,而像函数 update(),add() 却是直接改变对象本身的,为了形象,我把此类直接改变自身的函数成为“自变”。
此处,我再介绍几种典型的“自变”函数,其实这些函数大多数情况下可以用操作符或者其他函数替代
(1) s.intersection_update(t):令s中只保留与t的交集
a = {1,2}
a.intersection_update(b)
print(a) # >>> {1,2}
其实,上面函数等价于 a &= b
类似的函数还有 s.different_update(t),s.symmetric_difference(t) 等等,都是类似的道理
(2) s.discard(obj):若s中有obj,从s中删除它。和remove() 函数相比,当删除一个s中不存在的对象时,不删就是,不会报错。
a = {1,3}
a.discard(2)
print(a) # >>> {1,3}
a.discard(5)
print(a) # >>> {1,3}
(3) s.clear() 清空整个集合。这个就不举例了