3.5 元组和集合
元组和集合都不是很常用的变量类型,因为有很多时候编程不是一种语言就能写完一个程序的,比如说一个网页就需要用到前端语言和后端语言,类似的情况可能经常会遇到。所以有时候一种变量如果不是两种语言都支持的话还要想一些方法去转换,影响开发效率,而有其他变量可以替换就不会选不常用的变量。但并不是说这就没有用了,只不过是特定场景没有使用到而已,我们还是需要了解这两种变量类型的,其中的元组更为常见一些,但还是看场景,有些应用就是需要集合。
1、元组
元组(tuple)的表达形式和数组(也就是列表)差不多,只是把数组的中括号[ ]换成圆括号( )。可以看下面例子:
tup1 = ('NetEase', 'ICBC', 2020, 1994)
tup2 = (1, 2, 3, 4, 5)
我们按之前的套路来看元组的“查改增删”

我们看上面的例子,其实元组的访问和列表一样的,都是使用索引来访问。

我们再看一下上面的例子,当我们要修改元组的元素时,会发现出现一个报错。其实这就是元组和列表最大的不同,就是元组内的元素时不能修改的,也就是既然有了列表还需要元组的原因。因为在一些情况下,我们希望定义一个值可以像列表一样方便调用但又不会被改变,我们就可以定义元组。

上面例子我们可以看到,元组也是不允许增加的。虽然元组不允许增加,但是我们可以通过元组间相加来得到一个新的元组,如下例子所示:

咦,奇怪,报错了,为什么呢?
因为元组内如果只有一个元素,是需要在该元素加一个逗号的,不然python会认为你只是在一个变量外加了个括号而已,我们可以打印类型看一下:

我们重新在上面例子的tup2元组元素后加逗号试试

我们可以看到,元组的确是可以相加的。
如果元组不能新增,那应该也是不能删除的,我们再用例子试一下:

我们可以看到,无论是用pop()函数还是remove()函数,元组都会报错,说明元组是不可以使用pop()和remove()删除一个元素的,但我们下面使用del是能够删除整一个元组的,元组删除后如果再打印出来是会报错的,报错信息是“name 'tup1' is not defined”,tup1没有定义,说明tup1不存在,已经删除了。
2、集合
集合的样子也和列表差不多,就是把列表的中括号[ ]换成花括号{ },下面举例来看:
set1 = {'NetEase', 'ICBC', 2020, 1994}
set2 = {1, 2, 3, 4, 5}
那集合跟元组和列表有什么区别?
集合(set)是一个无序的不重复元素序列。无序和不重复就是与元组和列表最大的不同。这个不重复的特性有个好处在于如果列表需要去重可以转换成集合再转换成列表即可。
需要注意的是,因为集合是使用花括号,字典也是使用花括号,所以如果需要定义一个空的集合,需要写成set() 而不是{},如下:

但如果集合内有内容,就可以用花括号直接定义了,当然也可以写成set()形式,如下例子,我们可以通过其他类型转化成set类型

我们还继续用“增删查改”来学习集合的部分。我们知道集合没有像列表和元组一样拥有索引来查看元素,也不能像字典一样调用key,但是我们想想,我们何必要去查看一个无序不重复的组合数据里面的单一个元素呢?我们知道全部元素就好啦,或者我们能判断这个组合有是否包含了某元素就好啦。就像下面例子。

集合的新增可以用add()函数,如下面例子:

我们可以看到add()函数可以为一个集合新增一个元素,但不能为其添加多个元素,换句话说,是将两个集合合并成一个集合。这种情况我们可以用一个新的函数实现,update()

再说说集合的删除,删除集合的元素主要有三种方法:remove(), discard(), pop()。我们分别来说一下这三种方法的区别:
remove()函数的使用如下:

我们可以看到使用set1.remove(5000)就可以将5000这个元素从集合set1中删除。
但是如果我们不确定一个元素是否在这个集合里面的时候,如上面例子,我们remove('MS')这个不存在于set1的元素,就会出现KeyError的报错。
另一方面,如果我们想删除一个子集合,使用remove也是会报错的。
我们再说另一个函数,discard(),如下面例子,删除一个不存在的元素‘MS’的时候,就算其不存在,也是不会报错的。而且discard()函数也是不可以删除一个子集合的。

前面两个函数remove()和discard()都不可以删除一个子集合,那么pop()函数可以吗?很遗憾,不行。
那么pop()函数有什么用,pop()其实是删除这个集合的最左元素。值得注意的是,因为集合是无序的,所以pop()出来的是随机的,同一个集合可以pop()出不同的元素。如下图。

说完上面三种删除函数的方法,我们还留有一个问题,一个集合如何删除一个子集合?
其实用一个减号也就可以了。

还有一个删除的操作,clear()函数,直接清空。
“增删查改”,只剩下“改”。那么集合能修改元素吗?不能,因为无序,想要修改直接删除一个元素再添加一个元素不就可以了吗?
如果学习过中学数学的我们就知道,数学上有一个集合得到概念,其实是类似的,使用python的集合,我们也可以实现交集、并集、差集的操作,而且正因为这类的操作十分方便而被常常使用。
交集:两个集合去相交的部分

用代码表示:

并集:两个集合合并(重叠部分只取一个)

用代码表示

差集:两个集合取不同的部分

用代码表示

所以我们上面说的删除一个子集合的操作,其实用的是差集的意思,换个说法而已。