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