查看原文:https://mp.weixin.qq.com/s/3l6kfWgxBvyjsFfTDfF9rw
Part1前言
上期文章我们学习了 Python 组合数据类型中的列表,详细介绍了列表增、删、改、查元素操作方法以及其他相关函数。
本期文章,我们将学习 Python 组合数据类型中的集合,为了更好地介绍集合类型,我们还将引入 Python 中可变数据类型与不可变数据类型的概念。
Part2集合有哪些特点
Python 中的集合是最典型的集合类型,Python 语言中的集合与数学中的集合概念十分相似,还记得数学中集合的三大特性吗?请看下表。
上表中的集合三大特性依然适用于 Python 中的集合。不同的是,Python 中数据类型十分多样,Python 集合能够存储的类型也不少,并不限于数字。为了能够满足集合的确定性与互异性,Python 集合要求其中的元素必须是确定的数据,既保证存入的数据不能再次发生变化。这种不能再次改变的数据类型就是 Python 中的不可变数据类型,与之相反的则是可变数据类型。
Part3什么是可变数据类型,什么是不可变数据类型?
Python 中所有的数据类型可以被分为两类,一类是可变数据类型,另一类是不可变数据类型,没有模棱两可的情况。
从字面意义上解释,可变数据类型在创建之后,还可以再进行增、删、改等操作。比如列表就属于可变数据类型,我们定义一个列表之后,还可以向列表中添加元素、删除元素或者修改列表中的元素,如下图所示。
而不可变数据类型在定义之后就不会再发生变化,始态即终态。比如字符串就是不可变类型,如下图所示。
从内存层面来说,我们在定义(或声明)一个变量的时候,系统会在内存中开辟出一块空间,用来存放这个变量被赋予的值,而这个变量(名)存储的,并不是存放在内存空间的数据值,而是这个值所在指向这块内存空间的内存地址。变量(名)正是通过内存地址来访问数据的。可变数据类型与不可变数据类型的定义也是从这个角度出发的:
可变数据类型:变量引用的数据类型,在更改数据的时候,不会开辟新的内存空间来保存修改后的数据,此数据类型为可变数据类型。
不可变数据类型:变量引用的数据类型,在更改数据的时候,会开辟新的内存空间来保存修改后的数据,此数据类型为不可变数据类型。
在 Python 中,可以使用 id() 函数来查看变量名所引用数据的内存地址,如下图所示。
当我们修改可变数据类型列表的值,并查看修改前后该列表的内存地址,会发现内存地址没有变化,即系统没有开辟新的内存空间来存储修改后的列表,如下图所示。
当我们 “修改” 不可变数据类型字符串的值,并查看修改前后该字符串的内存地址,会发现内存地址发生了变化,说明系统开辟了新的内存空间来存储修改后的字符串。事实上,我们并不是真的改变了字符串的值,而是将新的字符串重新赋值给了原来的变量名。如下图所示。
我们现在知道了可变数据类型与不可变数据类型之间的区别,那有没有什么方法快速检测一个数据是哪种数据类型呢?当然是有的。我们可以使用 Python 自带的 hash() 函数来查看数据的哈希值,如果数据是不可变数据类型,那该数据就是可哈希的,函数会直接返回该数据的哈希值;如果该数据是可变数据类型,由于可变数据是不可哈希的,程序会报告错误。
那么哈希值是什么呢?我们可以把哈希值理解为数据或文件的身份证。它是根据文件大小、时间、类型、创作者,机器等计算出来的,很容易就会发生变化,谁也不能预料下一个号码是多少,也没有能够更改他的软件。哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值被称为哈希值。也就是说,一台计算机在同一时间点,不可能存在两个不同的数据拥有同一个哈希值,而相同的(不可变)数据必然拥有一样的哈希值。Python 集合在计算机正是使用哈希值来判断是否出现重复的元素并去重,如果有多个哈希值相同的元素,则自动保留其中一个。由于哈希算法的运算效率非常高,这使得集合类型的运算性能也非常可观。
介绍完可变数据类型与不可变数据类型的区别,那么在 Python 基础数据类型中有哪些是不可变数据类型,哪些是可变数据类型呢?如下表所示。
注意上表中的集合是可变数据类型。虽然集合只存储不可变类型的数据,但集合存在增、删等操作,能够动态变化,所以集合属于可变数据类型。不像列表中还能存储列表一样,集合中就不能再存储集合了。
Part4如何创建集合
Python 集合是无序的组合类型数据,集合中各元素之间使用逗号分隔,所有元素被包裹在花括号 {} 中。集合的形式如下图所示。
创建集合时,仿照上图中的形式即可,但是要注意集合中只能存储不可变数据类型,如下图所示。
如果想要创建空集合,我们不能直接将一对花括号赋值给变量,这是因为 Python 中的字典也是使用花括号括起来的,系统默认一对空的花括号是一个空字典,而不是一个空集合。演示代码和正确创建空集合的方法如下图所示。
除了上面这种方式之外,我们还可以使用 set() 函数将具有序列属性的一维对象转化为集合,前提是该一维对象中不含可变数据类型。转化为集合后,会自动删除原序列中重复出现的元素,每个元素至多出现一次。示例代码如下图所示。
另外,我们还可以使用 list() 函数将集合转为列表,这样一来,我们就可以利用集合的互异性来对列表进行去重,这也是集合类型极其常见的使用场景,具体怎么操作呢?我们先使用 set() 函数将待去重的列表转为集合,这一步就完成了去重的工作,随后再使用 list() 函数将得到的集合转回列表即可。这样做有一点需要注意,由于集合的无序性,列表转集合的过程中,列表元素的顺序会被打乱。示例代码如下图所示。
Part5如何增、删、改、查集合中的元素
1集合中添加元素
使用 add() 函数向集合中添加元素,每次添加一个元素,如果要添加的元素已经在集合中出现了,那么此次操作是无效的,但程序不会报错。示例代码如下图所示。
除了上述方法之外,还可以使用 update() 函数一次性向集合中更新多个元素,使用方法如下图所示:
2删除集合中的元素
我们可以使用 remove() 函数删除集合中指定的元素,如果要删除的元素不在集合中,程序会报错,使用示例如下图所示。
如果不希望看到报错,我们可以使用 discard() 函数来删除集合中的元素,它与 remove() 的区别在于,如果要删除的元素不在集合中,则不执行任何操作,也不会报错。使用示例如下图所示。
除此之外还有一个 pop() 函数能够删除集合中的元素,它的功能是随机删除集合中的一个元素,如果使用 pop() 执行删除元素操作前集合已经是空集合了,那么程序会报错。使用示例如下图所示。
同列表的操作方法类似,也存在清空集合这种操作,用法与清空列表完全一致,都是使用 clear() 函数。使用示例如下图所示。
3修改集合中的元素
由于集合是无序的,没有索引属性,我们无法直接从集合中获取元素,所以不能直接修改集合中的元素。但可以另辟蹊径,如果想要修改集合中的元素,我们可以先删除需要改变的元素,再将新的元素添加到集合中即可;或者先将集合转为列表,随后修改列表中的元素,最后再将其转回集合。
4查找集合中的元素
集合类型不关心元素之间的顺序,它在乎的是元素是否在集合中。我们使用成员运算符 in 或 not in 可以直接判断元素是否在集合中。使用示例如下图所示。
如果想要查看集合中元素的数量,可以使用 len() 函数,这是一个公用的方法,适用于所有组合数据类型,使用示例如下图所示。
Part6集合运算(含案例)
还记得吗?我们学习数学中的集合时,曾经学过集合的运算,包括交集运算、差集运算、并集运算、补集运算等。这些运算同样存在于 Python 中。集合的运算在数据分析中的使用频率非常高,下面我们将举例说明。首先,给定两个元素不完全相同的两个集合 S、T,则两个集合之间的运算符号和功能如下表所示:
下面我们将通过几个实例来介绍集合运算的用法。
一位同学手中有两份数据,其中一份数据是截至2021年底杭州市有注册商标的农民专业合作社部分信息,导入到 Python 后变量名为 ShangBiao_data。样例数据如下图所示(一家合作社可能有多个商标)。
另一份数据是截至2021年底杭州市持有专利的农民专业合作社部分信息,导入到 Python 后变量名为 ZhuanLi_data。样例数据如下图所示(一家合作社可能有多个专利)。
这两份数据使用相同标准的 ID,也就是图中所示的合作社ID字段。我们先把两份数据的 ID 都转为集合,顺势计算出两份数据中合作社的数量。代码如下图所示。
经过计算,截至2021年底,杭州市持有商标的合作社有 992 家,持有专利的合作社有 63 家。下面我们使用集合运算来处理更加具体的问题。
1并集运算
问题:找出持有商标或申请专利的合作社,统计其数量。
这意味着我们需要求出两份数据共涉及多少家合作社,此时我们可以使用集合并集运算来解决问题,代码如下图所示:
根据集合并集运算,得出持有商标或者专利的合作社共有 1006 家,并且获得了这些合作社的 ID。
2差集运算
问题:计算仅持有商标,未持有专利的合作社数量。
根据问题,我们使用持有商标的合作社 ID 集合与持有专利的合作社 ID 集合做差集即可得到所需合作社的 ID。代码如下图所示。
根据集合差集运算,我们得到仅持有商标,未持有专利的合作社共 943 家,并且获得了这些合作社的 ID。
3交集运算
问题:计算同时持有商标和专利的合作社数量。
我们使用持有商标的合作社 ID 集合与持有专利的合作社 ID 集合做交集运算即可。代码如下图所示。
根据集合交集运算,我们得到同时持有商标和专利的合作社合作社共 49 家,并且获得了这些合作社的 ID。
4交集的补集
问题:获取仅持有商标、专利其中一项的合作社数量。
根据问题,我们可以使用集合的补集运算来解决问题,代码如下图所示。
根据运算,我们得到了仅持有商标、专利其中一项的合作社共 957 家,并且获得了这些合作社的 ID。
以上就是 Python 中组合数据类型——集合的详细介绍啦。
Part7结束语
本期文章我们详细介绍了 Python 中集合的概念以及相关操作方法。实际的数据处理中,使用集合进行去重以及集合的四种运算是最常见的,也是最重要的。
此外,了解集合的特性对学习另一种组合数据类型——字典也有巨大的帮助,下期文章我们将介绍剩余的两种组合数据类型,字典和元组。