编程语言
首页 > 编程语言> > Python集合(Set)

Python集合(Set)

作者:互联网

About

Python 2.3版本的时候,引入了一种新的数据类型——集合(set)。 集合是由序列(也可以是其他的可迭代对象)构建的,是无序的可变的数据类型。 Python中,集合用一对大括号“{}”表示,集合内的各元素用逗号分隔。

s = set()
print(s)  # set([])
s1 = {1, 2, 3}
print(s1)  # set([1, 2, 3])

注意集合字典的区别,字典虽然也是一对大括号,但是其内是键值对形式的,而集合是用逗号隔开元素的,大家创建集合时需注意。我们也可通过set()函数将列表、元组等其他的可迭代的对象转换为集合。

s = set([1, 2, 1, 3, 4])
print(s)  # 3.  {1, 2, 3, 4}

可以看出,转换的时候,集合会自动将元素去重,这也是集合的特性:集合内的每个元素都是唯一的,不可重复! 除此之外,集合的元素只能是不可变类型的数据类型,也就是可哈希类型,而比如列表,字典,和集合本身则不可作为集合的元素。

集合的基本操作

首先,我们来说,集合不支持什么操作:

集合不支持:索引、切片,复制,拼接

s = set(range(10))
print(s) # set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# print(s[0])  # TypeError: 'set' object does not support indexing
# print(s[0:3])  # TypeError: 'set' object has no attribute '__getitem__'
s1 = {'a', 'b'}
# s2 = s + s1  # TypeError: unsupported operand type(s) for +: 'set' and 'set'
s2 = s1 * 3  # TypeError: unsupported operand type(s) for *: 'set' and 'int'

可以看到,集合确实不支持这些!

成员资格测试

但是支持什么呀,没错,成员资格测试还是可以的。

s = set(range(10))
print(1 in s)  # True
print(1 not in s)  # False

for循环取值

s = set(range(10))
for item in s:
    print(item)
'''
0
1
2
3
4
5
6
7
8
9
'''

留个思考题,集合能while循环打印其中的值嘛?为啥能for循环取值? 虽然基本操作不多,但是常用方法不少。我们一起来看看。

集合的常用方法

set.add(obj)

为集合添加元素:

s = set()
s.add(1)
s.add(2)
s.add(1)
print(s)  # set([1, 2])

由于去重的特性,集合将重复添加的元素过滤掉了。

set1.update(set2)

s1 = {1, 2}
s2 = {1, 2, 3, 4}
s1.update(s2)
print(s1)  # set([1, 2, 3, 4])

通过set.update()将另一个集合(s2)更新到当前集合(s1)中。同样的,会去重。

删除之:set.pop(obj)

s = {1, 2, 3, 4}
print(s.pop())  # 1
print(set().pop())  # KeyError: 'pop from an empty set'

随机删除集合元素并将该元素返回,如果集合为空则抛出KeyError

set.remove() & set.discard()

set.remove() & set.discard()用来删除集合中的指定元素:

s = {1, 2, 3, 4}
s.remove(1)
print(s)  # {2, 3, 4}
s.remove('a')  # KeyError: 'a'
​
s1 = {1, 2, 3, 4}
s1.discard(1)
print(s1)  # {2, 3, 4}
print(s1.discard('a'))  # None
print(s1)  # {2, 3, 4}

注意,set.remove()和set.discard()都是用来删除指定的元素,但区别是set.remove()如果指定的元素不存在则会报错,而set.discard()不会报错,而是返回None。

del 删除集合

由于集合是无序的,所以,del只能删除整个集合:

s = {1, 2, 3, 4}
# del s[0]  # TypeError: 'set' object doesn't support item deletion
del s
print(s)  # NameError: name 's' is not defined

第一个报错是不能删除集合中的元素。第二个是之前已经将变量s删除,最后引用的时候,发现没有报的错。

set.clear()

set.clear()清空集合

s = {1, 2, 3, 4}
s.clear()
print(s)  # set()

集合的元素嵌套

前文中说集合中的元素只能是不可变类型的数据,所以,集合中的元素就只能是数字、字符串和元组。

s1 = {1, 2.3, 'abc', (1, 2, [3, 4])}  # TypeError: unhashable type: 'list'

由第二行的报错来看,元组要想称为集合的元素或者字典的key时,其内的元素必须全部为不可变类型才行。

集合的运算

现在提个需求,现有个培训学校欧德博爱开设了Python和Linux两门课程,来学习的同学都有如下情况:

那现在需求来了,我们要对这些同学的情况做统计,比如找出两门课都报了的同学? 那采用什么数据类型呢?这里先用列表举例。

learn_python = ['小a', '小b', '小c', '小麻雀', '葫芦娃']
learn_linux = ['小c', '小d', '小e', '小东北', '小麻雀']
learn_p_l = []
for p in learn_python:
    if p in learn_linux:
        learn_p_l.append(p)
print(learn_p_l)  # ['小c', '小麻雀']

那要找出只学习了linux的同学呢?

learn_python = ['小a', '小b', '小c', '小麻雀', '葫芦娃']
learn_linux = ['小c', '小d', '小e', '小东北', '小麻雀']
learn_l = []
for l in learn_linux:
    if l not in learn_python:
        learn_l.append(l)
print(learn_l)  # ['小d', '小e', '小东北']

这么做是不是特别麻烦?在Python中,懒惰既是美德!所以Python给我们提供了一种简便的方法,使用集合来做这些事情。

交集

首先来记住三个方法一个运算符:

示例:找出即学习了Python又学习了Linux的同学。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
​
new_set1 = learn_python.intersection(learn_linux)
print(new_set1)  # {'小麻雀', '小c'}
​
new_set2 = learn_python & learn_linux
print(new_set2)  # {'小麻雀', '小c'}
​
print(learn_python)  # {'葫芦娃', '小a', '小麻雀', '小b', '小c'}

intersection()方法将结果以新的集合形式返回,并没有改变原集合。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
​
learn_python.intersection_update(learn_linux)
print(learn_python)  # {'小c', '小麻雀'}

可以发现,intersection_update()方法求出结果后,并没有赋值给新的集合,而是将结果(set1 & set2)覆盖到(可以理解为先清空)set1集合中。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
learn_java = {'Neeo', 'Anthony'}
​
print(learn_python.isdisjoint(learn_linux))  # False
print(learn_python.isdisjoint(learn_java))  # True

可以发现,Python和Linux两门学科是有同学同时学习的,所以返回了False。而没有同学同时学了Python和学Java,所以返回了True。

并集

首先来记住求并集的方法和运算符:

示例:找出所有来欧德博爱学习课程的人。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
​
new_set1 = learn_python.union(learn_linux)
print(new_set1)  # {'小东北', '小c', '小e', '葫芦娃', '小d', '小a', '小麻雀', '小b'}
​
new_set2 = learn_python | learn_linux
print(new_set2)  # {'小东北', '小e', '小d', '小c', '小a', '小b', '葫芦娃', '小麻雀'}

差集 首先,来记住求差集的方法和运算符:

找出只学习了Python(或者Linux)课程的人。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
​
new_set1 = learn_python.difference(learn_linux)
print(new_set1)  # {'小b', '葫芦娃', '小a'}
​
new_set2 = learn_python - learn_linux
print(new_set2)  # {'小b', '葫芦娃', '小a'}
​
print(learn_python)  # {'小b', '葫芦娃', '小麻雀', '小c', '小a'}

可以看到,新的集合中,只保留了仅学Python学科的学生,并没有改变原有集合。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
​
learn_python.difference_update(learn_linux)
print(learn_python)  # {'葫芦娃', '小a', '小b'}

当前集合(learn_python)移除与集合(learn_linux)重复的元素后,将结果覆盖到当前集合中(learn_python)。

对称差集

首先,来记住求差集的方法和运算符:

示例:找出没有同时学习Python和Linux的学生。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
​
new_set1 = learn_python.symmetric_difference(learn_linux)
print(new_set1)  # {'葫芦娃', '小a', '小e', '小d', '小东北', '小b'}
​
new_set2 = learn_python ^ learn_linux
print(new_set2)  # {'小d', '葫芦娃', '小a', '小b', '小东北', '小e'}
​
print(learn_python)  # {'葫芦娃', '小麻雀', '小b', '小c', '小a'}

有前两个打印结果可以看到,移除两个集合的交集部分就是对称差集的结果。

learn_python = {'小a', '小b', '小c', '小麻雀', '葫芦娃'}
learn_linux = {'小c', '小d', '小e', '小东北', '小麻雀'}
learn_python.symmetric_difference_update(learn_linux)
print(learn_python)  # {'小e', '葫芦娃', '小b', '小东北', '小d', '小a'}

通过打印可以看到,在求完对称差集后,将结果覆盖到当前的集合中(learn_python)。

子集 & 超集

首先,来记住两个方法:

s1 = {1, 2}
s2 = {1, 2, 3, 4}
print(s1.issubset(s2))  # True
print(s1.issuperset(s2))  # False

上例,集合s1是另一个集合s2的子集,或者说集合s2是集合s1的超集。 还有一种情况需要注意:

s1 = {1, 2}
s2 = {1, 2}
print(s1.issubset(s2))  # True
print(s1.issuperset(s2))  # True

上例中,当两个集合元素一致时,两个集合的关系可以称为互为子集。

集合中的关系运算

在集合中,我们可以使用关系运算符来判断两个集合的包含关系。

s1 = {1, 2}
s2 = {1, 2, 3, 4}
print(s1 < s2)  # True
print(s1 <= s2)  # True
print(s1 > s2)  # False
print(s1 >= s2)  # False
print(s1 == s2)  # False
print(s1 != s2)  # True

在集合中,关系运算符符包括:

再次强调,在集合中,关系运算符只是表示两个集合的包含关系,而不是表示两个集合的大小关系。

方法 描述 重要程度
set.add(obj) 添加元素 *
set1.issuperset(set2) 判断当前集合是否为另一个集合的超集 ***
set1.issubset(set2) 判断当前集合是否为另一个集合的子集 ***
set1.sysmmetric_difference_update(set2) 求对称差集并将结果更新到当前集合内 ***
set1.sysmmetric_difference(set2) 对称差集:^ *
set1.update(set2) 另一个集合更新当前集合 *
set.copy() 浅拷贝 ****
set.discard(obj) 删除指定元素 *
set.pop() 随机删除集合内元素并将此元素返回 *
set.clear() 清空集合 ***
set.remove(obj) 删除指定元素 ****
set1.difference_update(set2) 求差集并将结果更新到当前集合内 ****
set1.difference(set2) 差集: - *
set1.union(set2) 并集: | *
set1. isdisjoint(set2) 两个集合没有交集返回True,否则返回False ***
set1.instersection_update(set2) 求交集并将结果更新到当前集合内 ****
set1.instersection(set2) 交集: & *

除此之外,还有以下内置函数可以应用于集合。

内置函数 描述 重要程度
len(set) 返回集合的元素个数 *
max(set) 返回集合内的最大元素 ****
min(set) 返回集合内的最小元素 ****
sum(set) 返回集合元素之和 ***
sorted(set) 排序集合内的元素 *

同样的,这些内置函数在应用于集合时,要注意集合内的元素类型,比如求最大或最小时,其中的元素必须是同类型,不然怎么比较呀!

总结 让我们来总结下:

 

 


Reference:

图片来源:RealPython

标签:set,Python,python,print,Set,set1,learn,集合
来源: https://www.cnblogs.com/cyberkid/p/16023652.html