本课介绍Python集合数据类型。集合不同于列表和元组类型,集合存储的元素是无序且不能重复的,同数学中的集合一样,集合可以执行集合的并、交、差运算。通过本课的学习,可以掌握集合类型的使用方法。
术语hashable
说一个对象是hashable,是指这个对象是可哈希的,一个对象可哈希是指这个对象可以被内置函数hash计算出哈希值。hash函数声明如下:
hash(object)
函数返回该object对象的哈希值(如果它有的话),返回的哈希值是一个整数。
可哈希性使得对象能够作为字典键或集合成员使用,因为这些数据类型要在内部使用对象的哈希值。
大多数 Python 中不可变类型的对象都是可哈希的,可变容器类型(例如列表或字典)都不可哈希;不可变容器类型(例如元组和 frozenset)仅当它们的元素均为可哈希时才是可哈希的。
认识集合类型
在数学概念中,集合是由一个或多个确定的元素构成的整体。具体来说是指具有某种特定性质、具体的或抽象的对象汇总成的集体,这些对象称为该集合的元素或成员。例如,在整数集合中,数值…、-1、0、1、2…是整数集合的元素。
在Python语言中,提供了集合类型,集合类型存储的元素无序且不能重复,作为一种无序的多项集,集合并不记录元素位置或插入顺序,相应地,集合也不支持索引、切片或其他序列类的操作。
目前,Python提供了两种集合类型,set 和 frozenset。set 类型是可变的 其内容可以使用 add() 和 remove() 这样的方法来改变。由于是可变类型,它没有哈希值,因此不能被用作字典的键或其他集合的元素。frozenset 类型是不可变的并且是hashable,其内容在被创建后不能再改变;因此它可以被用作字典的键或其他集合的元素。
创建一个set对象,需要使用{}括起来,set对象的元素都在{}括号内,元素之间用英文逗号分隔。

案例代码:
>>> s = {"java","Pyhon","C++"}
>>> t = {30,20,10}
>>> type(s)
<class 'set'>
>>>
set类型的对象也可以通过Python的内置函数set来创建,frozenset类型的对象只能通过Python的内置函数frozenset来创建。
set函数和frozenset函数具有相同的声明:
class set([iterable])
class frozenset([iterable])
参数iterable是可迭代对象,创建的集合对象的元素来自于iterable,iterable的元素必须是hashable。若没有给出iterable,函数将返回一个空的集合对象。
案例代码:
>>> # 创建set对象
>>> s = set(["java","C++"])
>>> print(s)
{'java', 'C++'}
>>> # 创建frozenset对象
>>> f = frozenset(["java","C++"])
>>> print(f)
frozenset({'java', 'C++'})
集合运算
set对象和frozenset都支持集合运算,集合运算主要有求集合的并集、交集、差集、对称差集运算。
集合的并集运算
集合的并集运算是把两个集合合并成一个新的集合,集合合并后重复的成员被删除。在Python语言中,使用集合运算符‘|’或集合对象的union(*others)方法,来执行集合的合并运算。
案例代码:
>>> #创建集合对象s1
>>> s1 = set(['变量','赋值','类','成员'])
>>> #创建集合对象s2
>>> s2 = set(['变量','赋值','接口','API'])
>>> #求s1和s2的并集
>>> A = s1 | s2
>>> print(A)
{'赋值', '成员', '变量', 'API', '类', '接口'}
>>> # 使用union方法求s1和s2的并集
>>> B = s1.union(s2)
>>> print(B)
{'赋值', '成员', '变量', 'API', '类', '接口'}
>>>
集合的交集运算
集合的交集运算是求两个集合的共有成员,两个集合执行交集运算后返回新的集合,该集合中的每个元素同时是两个集合中的成员。在Python语言中,使用符号‘&’或集合对象的intersection(*others)方法,来执行集合的交集运算。
案例代码
>>> #创建集合对象s1
>>> s1 = set(['变量','赋值','类','成员'])
>>> #创建集合对象s2
>>> s2 = set(['变量','赋值','接口','API'])
>>> #求s1和s2的交集
>>> A = s1 & s2
>>> print(A)
{'赋值', '变量'}
>>> # 使用intersection方法求s1和s2的并集
>>> B = s1.intersection(s2)
>>> print(B)
{'赋值', '变量'}
集合的差集运算
集合的差集运算是求A集合与B集合之间的差值,A集合与B集合执行差集运算后返回新的集合,该集合的元素,只属于集合A,而不属于集合B。在Python语言中,使用符号‘-’或difference(*others)方法,来执行集合的差集运算。
案例代码:
>>> #创建集合对象s1
>>> s1 = set(['变量','赋值','类','成员'])
>>> #创建集合对象s2
>>> s2 = set(['变量','赋值','接口','API'])
>>> #求s1和s2的差集
>>> A = s1 - s2
>>> print(A)
{'类', '成员'}
>>> # 使用difference方法求s1和s2的差集
>>> B = s1.difference(s2)
>>> print(B)
{'类', '成员'}
集合的对称差集运算
集合的对称差集运算是集合的异或运算,A集合与B集合执行对称差集运算后返回新的集合,该集合中的元素只能是属于A集合或B集合的成员,不能同时属于A和B集合。在Python语言中,使用符号‘^’或集合对象的symmetric_difference方法,来执行集合的对称差集运算。
案例代码:
>>> #创建集合对象s1
>>> s1 = set(['变量','赋值','类','成员'])
>>> #创建集合对象s2
>>> s2 = set(['变量','赋值','接口','API'])
>>> #求s1和s2的对称差集
>>> A = s1 ^ s2
>>> print(A)
{'类', '成员', 'API', '接口'}
>>> # 使用symmetric_difference方法求s1和s2的对称差集
>>> B = s1.symmetric_difference(s2)
>>> print(B)
{'类', '成员', 'API', '接口'}
集合元素的访问操作
集合类型的set和frozenset对象都支持下表所列出的操作。表中的s是指set和frozenset对象。

注释
(1)isdisjoint(other)是集合类型的方法,该方法用于检测对象s和other对象有没有共同的元素,如没有返回True。参数other是集合对象。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.isdisjoint({"php"})
True
>>> s.isdisjoint({"java"})
False
>>>
(2)issubset(other)是集合类型的方法,该方法用于检测对象s的元素是否都在对象other中。若在返回True。参数other是集合对象。
Python也提供了下面的运算符完成该方法同样的功能。
set <= other
运算符 “<=” 用于检测set对象的每个元素是否都在 other 之中。
set < other
运算符 “<” 用于检测set集合是否为 other 的真子集。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.issubset({"Python","java","C++"})
True
>>> s <= {"Python","java","C++"}
True
>>> s < {"Python","java","C++","PHP"}
True
(3)issuperset(other)是集合类型的方法,该方法用于检测other 中的每个元素是否都在集合s之中。
Python也提供了下面的运算符完成该方法同样的功能。
set >= other
运算符 “>=” 用于检测other集合的每个元素是否都在集合s 之中。
set > other
运算符 “>” 用于检测集合s是否为 other 的真超集。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.issuperset({"Python","java","C++"})
True
>>> s >= {"Python","java","C++"}
True
>>> s > {"Python","java","C++"}
False
>>>
要访问集合内的单个元素,需要先将集合转换为列表,然后再访问。
例如:
# A为集合元素
A = {1,2,5}
# 集合元素转换为列表元素
B = list(A)
temp = B[1]
1.1.1 集合的遍历
遍历集合可以使用for循环。
goods = {"牛奶","面包","牛肉"}
for item in goods:
print(item)
集合元素的更新操作
集合元素的更新操作只能用于set集合对象,不能用于frozenset集合对象。下表列出了set集合对象支持的更新操作。
下表中的s是set集合对象,other为集合对象。非运算符版本的update(), intersection_update(), difference_update() 和 symmetric_difference_update() 方法的other参数可为任意可迭代对象。

注释
(1)update(*others)是set集合对象的方法,该方法将 others 中的所有元素添加到集合s。参数other可以是任意的可迭代对象。
Python也提供了下面的运算符完成该方法同样的功能。
set |= other | ...
其中set和other都为集合对象。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.update(["php","HTML"])
>>> print(s)
{'Python', 'C++', 'php', 'java', 'HTML'}
>>> s |= {"Node"}
>>> print(s)
{'Python', 'C++', 'php', 'Node', 'java', 'HTML'}
>>>
(2)intersection_update(*others)是set集合对象的方法,该方法更新集合s,只保留在others 中也存在的元素。参数other可以是任意的可迭代对象。
Python也提供了下面的运算符完成该方法同样的功能。
set &= other & ...
其中set和other都为集合对象。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.intersection_update(["Python","java"])
>>> print(s)
{'Python', 'java'}
>>> s = {"Python","java","C++"}
>>> s &= {"Python","java"}
>>> print(s)
{'Python', 'java'}
>>>
(3)difference_update(*others) 是set集合对象的方法,该方法更新集合s,移除其中也存在于 others 中的元素。参数other可以是任意的可迭代对象。
Python也提供了下面的运算符完成该方法同样的功能。
set -= other | ...
其中set和other都为集合对象。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.difference_update(["java"])
>>> print(s)
{'Python', 'C++'}
>>> s = {"Python","java","C++"}
>>> s -= {"java"}
>>> print(s)
{'Python', 'C++'}
>>>
(4)symmetric_difference_update(other) 是set集合对象的方法,该方法更新集合s,只保留存在于集合的一方而非共同存在的元素。参数other可以是任意的可迭代对象。
Python也提供了下面的运算符完成该方法同样的功能。
set ^= other
其中set和other都为集合对象。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.symmetric_difference_update({"Python"})
>>> print(s)
{'C++', 'java'}
>>> s = {"Python","java","C++"}
>>> s ^= {"Python"}
>>> print(s)
{'C++', 'java'}
>>>
(5)add(elem)是set集合对象的方法,该方法将元素 elem 添加到集合s。elem是hashable。
案例代码:
>>> s = {"Python","java","C++"}
>>> s.add((10,20))
>>> print(s)
{'java', 'C++', (10, 20), 'Python'}
>>>
(6)remove(elem) 是set集合对象的方法,该方法从集合s移除元素 elem。 如果 elem 不存在于集合s则会引发 KeyError异常
案例代码:
>>> s = {"Python","java","C++"}
>>> s.remove("Python")
>>> print(s)
{'java', 'C++'}
>>>