Python2.3版本的时候,引入了一种新的数据类型——集合(set)。
集合是由序列(也可以是其他的可迭代的对象)构建的,是无序的可变的而数据类型。
Python中,集合用一对大括号"{}"表示,集合内的各个元素用逗号分隔。由不同元素组成的集合,集合是一组无序排列 可hash值,可作为字典的key;集合的目的是将不同的值存放在一起,不同的集合间用来做关系运算,无须纠结于集合中的单个值,也就是说集合中是没有重复元素的。通过者一特点,可以将带有重复元素的列表通过代码转换成集合,可以做去重操作,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
s = set()
print(s)
# 结果:set()
print(type(s))
# 结果:<class 'set'>
s1 = {1, 2, 3}
print(s1)
# 结果:{1, 2, 3}
字典和集合的区别,字典虽然也是一对大括号,但是期内是键值对形式的,而集合是用逗号隔开元素的。我们也可以用set()函数将列表、元组等其他可迭代的对象转换为集合。
lst1 = ['*','香港','广州','*']
s = set(lst1)
print(s)
# 结果:{'*', '香港', '广州'}
可以看到结果,再转换的时候,集合会自动将元素去重,这也是集合的特性:集合内的每个元素都是唯一的,不可重复!
除此之外,集合的元素只能是不可变数据类型,也就是可哈希类型,而比如列表、字典和集合本身则不可做为集合的元素!
集合的基本操作
集合不支持什么操作:
集合不支持:索引、切片、复制、拼接
s = set(range(10))
print(s)
# 结果:{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
print(s[1])
# 报错结果:TypeError: 'set' object is not subscriptable
print(s[0:5])
# 报错结果:TypeError: 'set' object is not subscriptable
set1 = {'a','b'}
set2 = set1 * 2
print(set2)
# 报错结果:TypeError: unsupported operand type(s) for *: 'set' and 'int'
通过 in 和 not in 判断元素是否存在
s = set(range(10))
print(1 in s)
# 结果:True
print(2 not in s)
# 结果: False
通过for 循环取值
s = set(range(50,66))
for i in s:
print(i)
# 结果:
'''
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
'''
也是遵循列表的闭区间
集合的常用方法
set.add(obj)
s = set()
s.add('太上老君')
s.add('太白金星')
s.add('玉皇大帝')
s.add('如来佛祖')
print(s)
# 结果:{'太白金星', '玉皇大帝', '太上老君', '如来佛祖'}
set1.update(set2)
s1 = {'葫芦娃','蝎子精','虎头怪','葫芦爷爷'}
s2 = {'李白','吕布','妖姬'}
s1.update(s2)
print(s1)
# 结果:{'蝎子精', '妖姬', '葫芦爷爷', '李白', '吕布', '虎头怪', '葫芦娃'}
也可以通过.update将另一个集合与当前集合做合并去重,如下栗子:
s1 = {'葫芦娃','蝎子精','李白','黑豹警长'}
s2 = {'李白','吕布','黑豹警长'}
s1.update(s2)
print(s1)
# 结果:{'黑豹警长', '蝎子精', '李白', '葫芦娃', '吕布'}
删除:set.pop(obj)
s1 = {'德玛西亚','皇子','薇恩','盲僧','皮城女警'}
print(s1.pop())
# 结果:盲僧
print(set().pop())
# 结果:KeyError: 'pop from an empty set'
随机删除集合元素并将该元素返回,如果集合为空则抛出KeyError
。
set.remove() & set.discard()
set.remove() & set.discard()
用来删除集合中的指定元素:
s1 = {'德玛西亚','妖姬','薇恩','盲僧','皮城女警'}
s1.remove('德玛西亚')
print(s1)
# 结果:{'盲僧', '薇恩', '皮城女警', '妖姬'}
s2 = {'唐僧','孙悟空','猪八戒','沙僧'}
s2.discard('唐僧')
print(s2)
# 结果:{'沙僧', '猪八戒', '孙悟空'}
注意,set.remove()和set.discard()都是用来删除指定的元素,但区别是set.remove()如果指定的元素不存在则会报错,而set.discard()不会报错,而是返回None。
del 删除集合
由于集合是无序的,所以,del只能删除整个集合:
s2 = {'如来','大鹏','虎头怪','白骨精'}
del s2
print(s2)
# 结果:NameError: name 's2' is not defined
set.clear() 清空集合
s1 = {'金牛座','双子座','天秤座','天蝎座'}
s1.clear()
print(s1)
# 结果:set()
集合的元素嵌套
集合中的元素只能存放不可变数据类型的数据,所以,集合中的元素就只能是数据、字符串和元组。
set1 = {'abc',123,(['a','b'],1,2)}
print(set1)
# 结果报错:TypeError: unhashable type: 'list'
集合的运算
现在有一个需求,现有一个学校班德卢,开设了Python和Linux两门课程,来学习的同学都有如下情况:
- 有的同学学习Linux
- 有的学习Python
- 还有的既学了Linux又学了Python
需要我们对学生的学习情况做统计,比如找出两门课都报了的同学有哪些?
那么采用什么数据类型呢?先用列表举例。
Python = ['刘备','张飞','关羽','赵云','黄忠']
Linux = ['诸葛亮','刘备','赵云','许褚']
Py_Li = []
for p in Python:
if p in Linux:
Py_Li.append(p)
print(Py_Li)
# 结果:['刘备', '赵云']
那要找出只学习了Linux课程的同学呢?
Python = ['刘备','张飞','关羽','赵云','黄忠']
Linux = ['诸葛亮','刘备','赵云','许褚']
Li = []
for p in Linux:
if p not in Python:
Li.append(p)
print(Li)
# 结果:['诸葛亮', '许褚']
在Python 中,懒惰是美德!所以Python给我们提供了一种简便的方法,使用集合来做这些事情。
交集
首先来记住三个方法一个运算符:
- set1.intersection(set2, set3...),以新集合的形式返回两个或多个集合的交集。
- set1.intersection_update(set2),两个集合求交集(大家都有的),然后将结果覆盖(相当于先对set1做clear操作)到当前(原地操作,并没有产生新的集合)集合中(set1)。
-
&
运算符,intersection()方法对应的运算符,其实就是简写形式。 - set1.isdisjoint(set2),该方法用来判断两个集合是否有交集,如果有交集,返回False,没有交集返回True。
示例:找出即学习了Python又学习了Linux 的同学:
Python = {'刘备','张飞','关羽','赵云','黄忠'}
Linux = {'诸葛亮','刘备','赵云','许褚'}
Py_Li = Python.intersection(Linux)
print(Py_Li)
# 结果:{'赵云', '刘备'}
intersection() 方法将结果以新的集合形式返回,并没有改变原集合。
Python = {'张无忌','张三丰','张翠山','白眉鹰王','葫芦娃'}
Linux = {'乔峰','虚竹','张无忌','张三丰'}
Python.intersection_update(Linux)
print(Python)
# 结果:{'张无忌', '张三丰'}
可以发现,intersection_update()方法求出结果后,并没有赋值给新的集合,而是将结果(Python & Linux)覆盖(可以理解为先清空,后添加)Python集合中。
Python = {'张无忌','张三丰','张翠山','白眉鹰王','葫芦娃'}
Linux = {'乔峰','虚竹','张无忌','张三丰'}
Java = {'孙悟空','诸葛亮','蒋介石'}
print(Python.isdisjoint(Linux))
# 结果:False
print(Python.isdisjoint(Java))
# 结果: True
结果表明,Python和Linux两门学科是又同学即学习Python又学习Linux,所以返回了False,而没有同学即学习Python又学习Java,所以返回了True。
并集
求并集得方法和运算符:
- set.union(set2,set3),该方法以新集合的形式返回两个或多个集合的并集,既包含了两个集合的所有元素,又将重复的元素去重。(去重)
- |, 求集合并集的运算符为管道符 | 。
示例:找出所有来班德卢学校学习课程的人。
Python = {'张无忌','张三丰','张翠山','白眉鹰王','葫芦娃'}
Linux = {'乔峰','虚竹','张无忌','张三丰'}
stu_all = Python.union(Linux)
print(stu_all)
# 结果为:
{'葫芦娃', '张翠山', '张三丰', '虚竹', '张无忌', '乔峰', '白眉鹰王'}
stu_all2 = Python | Linux
print(stu_all2)
# 结果为:
{'张三丰', '白眉鹰王', '葫芦娃', '乔峰', '张无忌', '虚竹', '张翠山'}
差集
差集的方法和运算符:
- set1.difference(set2, set3...),返回移除两个或多个集合中重复元素后的新集合,也就是只保留我自己(独有的)。
-
-
,求差集的运算符为-
。 - set1.difference_update(set2, set3...),该方法直接在原集合(set1)中移除重复元素,是原地操作,并没有返回值。
找出只学习了Python课程的同学:
Python = {'张无忌','张三丰','张翠山','白眉鹰王','葫芦娃'}
Linux = {'乔峰','虚竹','张无忌','张三丰'}
stu_Py = Python.difference(Linux)
print(stu_Py)
# 结果为:
{'张翠山', '白眉鹰王', '葫芦娃'}
stu_Py2 = Python - Linux
print(stu_Py2)
# 结果为:
{'白眉鹰王', '张翠山', '葫芦娃'}
结果反应除,新的集合中只保留了仅学习了Python课程的同学,并没有改变原有集合。
总结:
- 按照可变数据与不可变数据来说:
- 可变类型:列表、字典、集合。
- 不可变类型:数字、字符串、元组。
- 按照存放值的数量来说:
- 一个值:数字,字符串。
- 多个值:列表、元组、字典、集合。
注意,一串字符串在客观上也可以理解为一个元素,比如在列表中,字符串再长,也只是列表的一个元素。数字也一样。
- 按照取值方式:
- 直接取值:数字。
- 序列类型:字符串、元组、列表。
- 映射类型:字典。
至此,Python内置的数据类型,基本学习完毕。