集合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(……)的形式,如:

python中列表集合的表示符号(Python集合set的概念构造)(1)

2.3 用描述式生成集合

python中列表集合的表示符号(Python集合set的概念构造)(2)

3 set和其它类型的转换

tuple → set:要求tuple元素能用==比较,重复元素只保留一个,顺序丢失;

set → tuple:没有限制;

list → set:要求list元素满足set对元素的要求,重复元素只保留一个,顺序丢失;

set → list:没有限制;

str → set :集合元素是单个字符,重复字符只保留一个,顺序丢失;

dict → set:集合元素为字典里的关键字;

4 集合的比较

主要是比较集合之间的包含关系(一个集合的元素是否属于另一个集合),也就是子集与超集的关系。

如果一个集合的元素都属于另一个集合,则称前一集合是后一集合的子集,或称后一集合是前一集合的超集。显然,一个集合总是其自身的子集,也是其自身的超集。如果一个集合是另一集合的子集,而且两个集合不等,那么前一集合就是一个真子集,类似地,后一集合就是真超集。

也就是说,子集与超集的关系是包含或相等关系;而真子集与真超集则 是包含且不相等关系。

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)判断两个集合是否不相交,即是否有公共元素
5 集合运算

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的一个拷贝

python中列表集合的表示符号(Python集合set的概念构造)(3)

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-

,