集合set是Python定义的一种很重要的组合对象,在一个集合对象里可以汇集一批作为元素的对象,元素之间没有特殊关系。
集合set使用一对大括号作为定界符,元素之间使用逗号分隔,同一个集合内的每个元素都是唯一的,元素之间不允许重复。
Python有两个表示集合的类型:set和frozenset(冻结集合),两者的不同在于set是可变类型,而frozenset是不变类型。
1 概念集合的概念来自于数学。数学里的集合就是一批元素的汇集,其最重要的性质是可以回答某个元素e是否属于集合s,也就是说,判断e是否为s的元素。在与集合相关的讨论中,元素作为一个不加定义的概念,除了元素判断之外,集合还有一组重要运算,包括集合之间的子集判断、两个集合的并集、交集、差集运算等。这些运算都可以基于集合的元素关系定义。
程序里也经常需要具有集合性质的对象,Python为此提供了集合类型。我们可以把一批任意元素汇集在一起,构成一个set或frozenset类型的对象。这里主要讨论set,实际上,与元素变动无关的内容均适用于frozenset。
Python对集合的元素也有要求,它们只能是不变对象(可哈希),而且必须能做相等比较(用==运算符)。内置的数字、字符串、bool对象、元组都满足这些要求(不包含列表、字典、集合等可变类型的数据)。
Python提供了一个内置函数hash()来计算对象的哈希值,凡是无法计算出哈希值(调用内置函数hash()时抛出异常)的对象都不能作为集合的元素(当然也不能作为字典对象的“键”)。
由于基本概念源于数学,Python的集合同样支持元素判断,也支持各种重要的集合操作,包括并集、交集、差集等。除此之外,set类型还支持一批变动操作,包括加入或删除元素的操作,以及用一些扩展赋值运算符描述的变动操作。
2.2 使用set()转换,转换的对象可以是任意的序列或可迭代对象。
由于用花括号形式总是生成set(或字典),要生成不变集合frozenset的对象,只能用frozenset(……)的形式,如:
2.3 用描述式生成集合
3 set和其它类型的转换
tuple → set:要求tuple元素能用==比较,重复元素只保留一个,顺序丢失;
set → tuple:没有限制;
list → set:要求list元素满足set对元素的要求,重复元素只保留一个,顺序丢失;
set → list:没有限制;
str → set :集合元素是单个字符,重复字符只保留一个,顺序丢失;
dict → set:集合元素为字典里的关键字;
4 集合的比较主要是比较集合之间的包含关系(一个集合的元素是否属于另一个集合),也就是子集与超集的关系。
如果一个集合的元素都属于另一个集合,则称前一集合是后一集合的子集,或称后一集合是前一集合的超集。显然,一个集合总是其自身的子集,也是其自身的超集。如果一个集合是另一集合的子集,而且两个集合不等,那么前一集合就是一个真子集,类似地,后一集合就是真超集。
也就是说,子集与超集的关系是包含或相等关系;而真子集与真超集则 是包含且不相等关系。
5 集合运算
s1 <= s2 当且仅当s1为s2的子集时返回True s1.issubset(s2) 同上 s1 < s2 当且仅当s1为s2的真子集时返回True s1 >= s2 当且仅当s2为s1的超集时返回True s1.issupset(s2) 同上 s1 > s2 当且仅当s2为s1的真超集时返回True s1.isdisjoint(s2) 判断两个集合是否不相交,即是否有公共元素 Python集合提供了一组与数学的集合运算对应的运算。
s1.union(s2,…) 并运算生成一个新集合 s1 | s2 | … 同上 s1.intersection(s2,…) 交运算生成一个新集合 s1 & s2 & … 同上 s1.difference(s2,…) 差运算生成一个新集合 s1 - s2 - … 同上 s1.symmetric_difference(s2) (s1 - s2) | (s2 - s1) s1.copy() 生成s1的一个拷贝 6 修改和更新集合
s1.update(s2,…) 修改s1,使之包含属于其他集合的元素 s1 |= s2 | … 同上 s1.intersection_update(s2,…) 修改s1,使之包含同属所有集合的公共元素 s1 &= s2 & … 同上 s1.difference_update(s2,…) 修改s1,从中去除属于其他集合的元素 s1 -= s2 - … 同上 s1.symmetric_difference_update(s2) 修改s1,使之包含仅属于s1或s2之一但不同时属于两者的元素 s.add(x) 将元素x加入集合s s.remove() 从s里删除元素x,在s没有x时报错 s.discard(x) 如果s里有x就抛弃它,没有x时什么也不做 s.pop() 从s里删除某个(任意)元素并返回它,具体元素由集合内部确定。如果操作时s为空则报错 s.clear() 清除s里的所有元素 附原码:
x = 2
s1 = {x,x 5,x**10} # 直接使用定义构造set集合
s2 = {'Chinese','Math','English','Physics','Chemisty','biology','Math'}
print(s1,'\n',s2)
'''
{1024, 2, 7}
{'Chemisty', 'Math', 'Physics', 'Chinese', 'biology', 'English'}
'''
# set基于"=="判断元素是否重复,如果重复,后面的舍弃掉
print({1,1.0})
print({1.0,1})
print({1,True})
print({False,0})
print({1,1.0,True,0,False})
'''
{1}
{1.0}
{1}
{False}
{0, 1}
'''
lis = [1,1,2,3,5,8,13]
tup = (1,7,13,19,23,29)
print(set(lis)) # 使用set()转换list构造set
print(set(tup)) # 使用set()转换tuple构造set
print(frozenset(lis)) # 使用frozenset转换list构造frozenset
'''
{1, 2, 3, 5, 8, 13}
{1, 7, 13, 19, 23, 29}
frozenset({1, 2, 3, 5, 8, 13})
'''
# 用描述式生成集合
s3 = {x*y for x in range(10) for y in range(10) if x*3 < y**2}
'''
相当于以下代码:
s3 = set()
for x in range(10):
for y in range(10):
if x*3 < y**2:
s3.add(x*y)
'''
fs = frozenset(n ** 2 for n in range(-10, 20))
print(s3,'\n',fs)
'''
{0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25,
27, 28, 30, 32, 35, 36, 40, 42, 45, 48, 49, 54, 56, 63, 64, 72, 81}
frozenset({64, 1, 0, 121, 100, 36, 4, 196, 225, 9, 169, 256, 324,
361, 289, 16, 81, 49, 144, 25}
'''
a = set('abracadabra') # unique letters in a
b = set('alacazam') # unique letters in b
print(a)
print(b)
print(a - b) # difference(差):letters in a but not in b
print(a | b) # union(联合): letters in either a or b
print(a & b) # intersection(交):letters in both a and b
print(a ^ b) # letters in a or b but not both
# sysmmetric difference(对称差集)letters in a or b but not both
'''
{'b', 'c', 'a', 'r', 'd'}
{'m', 'c', 'a', 'z', 'l'}
{'b', 'r', 'd'}
{'b', 'm', 'c', 'a', 'z', 'l', 'r', 'd'}
{'a', 'c'}
{'b', 'm', 'l', 'r', 'd', 'z'}
'''
-End-
,