2.2 Python中的基本数据类型

程序,本质上就是针对数据的一种处理流程。正是因为有了各种数据类型,程序才可以“有的放矢”地进行各种不同数据操作而不至于乱套。

下面我们重新回到关于Python基本数据类型的讨论上来。如前所述,在Python中,变量并不需要事先声明,但在使用前必须赋值。其实,在赋值过程中,该变量的类型及可被允许的操作才会确定下来。

在广义上,数据类型可分为标准数据类型和自定义数据类型。所谓自定义数据类型,就是面向对象编程中提到的概念——类(class)。而标准数据类型就是Python提供的7种内部数据类型,它们分别是Number(数值型)、Boolean(布尔类型)、String(字符串型)、List(列表)、Tuple(元组)、Dictionary(字典)及Set(集合)。下面分别对这几种基本数据类型进行简要介绍。

2.2.1 数值型(Number)

常用的数值型包括int(整型)、float(浮点型)、complex(复数类型)等。对于数值型的赋值和计算都很直观,就像在大多数编程语言中一样,大部分的变量只能有一个值,当某个变量被赋予一个新值时,旧值就会被覆写掉,代码如下所示。

我们可以用Python内置的type()函数查询对象的数据类型。Python是一门纯粹的面向对象的程序设计语言,对于不同的对象类型有不同的操作。有时候,我们需要借助type()函数为我们“验明正身”,代码如下所示。

需要特别说明的是,在Python中,使用变量前并不需要显式声明其数据类型。诸如上述代码中的变量x和y,它们都是在被赋值时根据等号(=)右边变量的数据类型,才“因地制宜”地变成了相应的数据类型。相比于C、C++、Java等强数据类型编程语言,这一点是显著不同的。

在Python中,我们可以给多个变量集体赋相同的值,代码如下所示。

上述赋值方式并没有特殊之处,很多编程语言都可以做到。但不同于C、C++和Java等编程语言的是,在Python中,允许在同一行给多个变量分别赋不同的值,代码如下所示。

下面我们对上述代码做简单解读。

(1)在Python中,我们可以同时为多个变量赋值,如a, b=1, 2。其实它相当于a=1,b=2。对于上面In [9]处输入的代码,其赋值示意图如图2-2所示。

图2-2 Python的多变量赋值

同样,我们也可以用type()函数分别验证上述三个变量的“身份”,代码如下。

(2)在Python中,一切皆对象。比如前面代码中提到的a, b, c=10, 4.7, 3+10j,实际上,等号左右两侧的都是一个对象——元组,每个元组内包含三个元素。当两个元组相互赋值时,实际上就是“丁对丁,卯对卯”,对应位置的元素相互赋值。关于元组的概念,本章后续会详细讨论。

(3)对于复数的表示,虚数部分的表示格式是“数值j”,而不是数学中常用的“数值i”。

(4)上面提及的a、b和c都是变量的标识。对于变量名称,Python是有讲究的,即标识符只能是字母、数字、下画线(_),但变量名不能以数字开头,并且中间不能包含空格。而且,Python中的标识符是区分大小写的,如name和Name是不同的变量。

下面我们再来简单演示一下基于数值型的运算,具体如下。

数值型的运算比较简单直观,但需要读者注意的有两点:数值的除法(/)总是返回一个浮点数(如2/4=0.5),要获取整数需使用双斜线操作符(//),如2//4=0;在多种数据类型混合计算时,Python会把整数转换成浮点数,即进行类型转换时趋向于精确化。

2.2.2 布尔类型(Boolean)

Python中的布尔类型常量有两个,True和False(注意首字母要大写),分别对应整型数字1和0。所以在严格意义上来讲,布尔类型属于前面讲到的数值型,可视为整型(int)的子类。例如,语句True+2的计算结果为3。

Python语言支持逻辑运算符,表2-1以a为100、b为200说明了Python中逻辑运算符的使用方法。

表2-1 Python中的逻辑运算符

需要特别注意的是,在Python中,任何非0和非null的情况都可视为True(有点类似于C或C++中的“非零即为真”),0或者null为False。

2.2.3 字符串型(String)

字符串(string,作为类别名称时用str表示)是由一系列字符组成的,它对文本数据的处理非常重要。在形式上,将一系列的字符用单引号(' ')或双引号(" ")包裹起来即可得到字符串,同时可用反斜杠“\”表示特殊的转义字符。

例如,"123"和'abc'都是字符串。尽管"123"看起来像一个整数,但一旦被一对单引号或双引号包裹起来,那它就是一个由三个不同字符构成的字符串对象。下面简单演示字符串的应用。

我们可以使用加号运算符(+)将不同的字符串连接在一起,甚至还可以用“* n”操作表示前面的字符串被重复了n次,示例如下。

我们可以通过内置函数len()求得字符串的长度,示例如下。

需要注意的是,len()函数求得的字符串长度包括任意字符。例如在上述字符串对象s中,world前面是有一个空格的,该字符在屏幕上是不可见的,但它也是客观存在的。因此,len()在进行字符计数时也会将其考虑在内。

我们可以通过方括号[]内的索引(从0开始)来访问字符串内的某个字符,示例如下。

此外,由于字符串对象是不可变的(immutable),所以一旦某个字符串被赋值,该字符串就被视为一个常量。例如,如果我们尝试把索引值为0的字符'h'修改为大写字符'H',以下这种尝试将不会被Python解释器允许。

执行上述代码会返回错误信息“TypeError: 'str' object does not support item assignment”(str对象是不支持赋值的)。这个提示信息告诉我们,str对象是不支持变量值更新的,即保持常量属性。

在Python中,字符串作为一种重要的数据类型,提供了很多好用的方法(method)在Python中,全局的、内置的、不依附于对象的功能块,称为函数(function),而依附于对象的功能块通常称为方法(method)。但在实际应用中,两者区别并不大,经常混称,并无大碍。,我们可以通过dir命令来查看这些方法。

由于可用的方法太多,所以在上述输出结果中,我们省略了大部分不常用的方法。当然,这里所言的“不常用”,也是因人而异的。幸运的是,Python内置函数的命名方式很好,对于大部分函数,即使我们没有用过,也能见名知意(了解其功能)。假设我们对某个方法的使用的确不熟悉,该怎么办呢?除了查询相关的手册,我们还可以用help命令来寻求在线支持。比如说,我们想知道split()方法该如何用,可以如下操作。

通常,help提供的信息是够用的。上述信息告诉我们,split()方法的功能是,通过指定分隔符(sep)对字符串进行分片(默认的分隔符可以是任意空白字符,包括空格、换行、制表符等)。参数maxsplit表示最大分割次数,默认为-1,即分隔所有满足要求的字符串,一般采用默认值即可。split()方法返回的是分割后的各个子字符串列表。下面我们举例说明它的用法。

我们再解释一个常用的字符串处理方法title(),它的功能是“标题化”字符串,也就是说,让所有单词的首字母都为大写形式,其余字母均为小写形式。

下面我们简单介绍一下比较常用的format()方法。该方法通过字符串中的花括号({})和冒号(:)这两个符号,尝试代替早期类C语言风格的格式化输出界定符号(%)。format()方法可接受不限个数的参数,且其显示位置也可以不同于出现的顺序。

该方法内部的参数就是我们要格式化输出的变量。如果不指定位置,则默认按照顺序依次往{}中“填空”,即format()中的第0个参数,就填在第0个{}之内,format()中第1个参数,就填在第1个{}之内,以此类推。

此外,我们还可使用花括号和数字n搭配的方式(即{n})在花括号中插入format()方法中第n个参数(n从0计数)。这时,n出现的顺序可“不按常规出牌”,代码如下所示。

除此之外,我们还可以在参数索引后面添加冒号(:),在冒号之后添加特定的输出格式。

有关字符串处理的方法有很多,这里就不展开讨论了。读者朋友可以边学边查边用,切不可重造轮子。

上面我们讨论的数据类型,都是Python的基本数据类型,它们是数据表达的基础。下面我们将介绍Python中另外四种相对复杂但常用的数据类型:列表(List)、元组(Tuple)、字典(Dictionary)和集合(Set)。

2.2.4 列表(List)

列表是Python中最常用的。它非常类似于C、C++、Java等语言中数组的概念。创建列表并不复杂,只要把不同的数据项用逗号(半角)分隔,并整体使用方括号([])括起来即可。如下面的代码所示。

不同于C、C++、Java中数组的地方是,Python列表中各个数据项的类型并不需要都是相同的,我们可将其视为一个“大杂烩”数组。在数据处理上,有点类似于孔子说的“有教无类”。

访问列表中的元素非常便利,和访问数组元素类似,可以通过方括号和索引值访问对应的元素。类似于数组,列表中的每个元素都被分配了一个数字,即相对于列表起始位置的偏移(offset),也可称之为索引,索引的起始编号是0。因此,正向索引时,第1个元素的索引是0,第2个元素的索引是1,以此类推。

除此之外,列表还支持反向索引:方括号内的偏移量为-1,表示倒数第1个元素;偏移量为-2,表示倒数第2个元素;以此类推。列表的索引示意图如图2-3所示。

图2-3 列表的索引示意图

在In [5]处,我们使用了列表的负数索引值,这在C、C++、Java等语言中是绝对禁止的,因为这会产生数组越界,但在Python中却属稀松平常之举。对于正向索引,索引值与我们的日常编号错1位,如索引为0表示第1个元素,索引为1表示第2个元素,以此类推。反向索引不存在错位问题,-1就表示倒数第1个元素,-2表示倒数第2个元素,以此类推。

不同于字符串对象的不可变属性,列表内部元素的值是可变的(Mutable),也就是说列表元素的值是可以修改的,代码如下所示。

鉴于列表的强大功能,也有人将其称为“打了激素的数组”。这么说也有道理,因为利用它还可以构建出“鱼龙混杂”的嵌套列表,如下所示。

利用列表的索引(即下标),我们可以每次从列表中获取一个元素。但如果我们想一次获取多个元素,该怎么办呢?这也很容易解决。在Python中,可利用列表分片(slice)来实现这个需求,代码如下所示。

通过在列表中插入一个冒号(:)可以分割两个索引值,冒号左边的数值是索引起始值(如前面的0),冒号右边的数值是索引结束值,但不包括该值(up to but not including),所以分片区间在严格意义上是“左闭右开”的,如上面代码的分片维度实际为[0:5)。

需要说明的是,列表分片后并不会破坏原有的列表,而是根据语法规则建立了一个原有列表的部分副本。在分片操作之后,我们可在IPython中输入print(list1)来查看这个列表是否发生了变化。

事实上,以语法简单而称著的Python,还提供了很多“语法糖”(Syntactic Sugar,即某些对语言功能没有影响但更方便程序员使用的语法)。例如,如果我们省略了冒号前面的数字,分片的索引起始值默认从0开始;如果省略冒号后边的数字,则表示分片以列表最后一个元素为终;如果两个边界都省略,只有一个冒号,表示从始到终输出所有元素。代码如下所示。

实际上,分片操作还可以接收第三个参数,即步长(step)。如果我们使用步长参数,列表方括号中的冒号就变成两个。步长在默认情况下值为1,有了这个默认值,在前面的代码中,方括号中可省略一个冒号。如果我们把步长改为其他值,这时方括号中的第二个冒号就不可以省略,代码如下所示。

列表的功能很强大,这一点还体现在它能实现“加法”与“乘法”操作上,这两种操作能分别完成列表的连接(Concatenate)和整体批量复制,代码如下所示。

列表还可以和字符串配合使用,达到神奇的“炸开”效果,代码如下所示。

除了上述基本操作,列表本身还封装了很多好用的方法,下面我们列举其中几个方法的用法。

2.2.4.1 添加列表元素

添加列表元素的方法有三个:append()、insert()和extend()。下面分别给予简单介绍。

●append():在列表尾部添加一个新元素。

●insert():在列表中的指定索引位置“插入”一个元素。

●extend():把一个列表整体“扩展添加”到另外一个列表的尾部。

这三个操作都属于原地(in place)操作。也就是说,被操作的列表,其内存地址(可以理解为列表对象独一无二的标识)不会因为上述三种操作而发生变化,依然原地待命,如图2-4中的代码所示。

图2-4 增加列表元素的方法

运行图2-4中的程序,观察结果:通过内置函数id()检测发现,在经过多种方法操作之后,列表对象fruits的内存地址始终如一,这就是“原地操作”的内涵。在Python中,id()函数是一个常用的内置函数,用于获取对象的内存地址。

2.2.4.2 删除列表元素

删除列表中的元素也有三种常见的方法,它们分别是pop()、remove()和clear()。

使用pop()时,如果不指定索引值(index),则默认值为-1,即弹出(删除)列表中最后一个元素。若添加其他索引,则根据给定索引值实施弹出操作。

如果不用索引作为参数,则可采用remove(x)方法,此处x表示要被删除的数值。该方法用于删除列表中第一个与指定值(x)相同的元素。

列表还有一种将全体元素清空的方法,那就是clear()。

上述三种方法都属于原地操作范畴。此外,我们还可利用全局内置函数del()删除列表中指定位置的元素。该函数不隶属于任何数据类型,可以理解为它是公用的静态函数。它也属于原地操作范畴,示例代码如下。

2.2.4.3 列表元素的计数与索引

列表中的count()方法也很常用,它能够统计某个元素在列表中出现的次数。

如果我们想从列表中找出某个给定值的第一个匹配项的索引位置,则可以采用index()方法。

如果仅仅是判断某个元素是否存在于列表之中,使用运算符in(出现)或not in(不出现)即可,这些方法会返回一个True或False的布尔值。代码如下所示。

2.2.4.4 列表元素的排序与逆序

列表还为我们提供了非常方便的排序和逆序输出功能。前者使用的方法是sort(),后者使用的方法是reverse(),示例代码如下。

在上面代码的In [30]处,我们使用列表的sort()方法对原列表元素进行排序,默认规则是直接比较元素大小。如果在sort()方法内指定参数,则可完成特定规则的排序。sort()方法原型如下。

该函数的三个参数都有默认值,也就是说,如果不指定值,它们会启用等号(=)后面的默认值。其中,cmp是可选参数,如果指定了该参数(通常是一个指定排序规则的函数),sort()方法会使用该参数描述的规则进行排序。key用来指定排序比较的元素。reverse用来指定排序的升降规则,reverse=True表示降序,reverse=False表示升序(默认)。

除了可用Python列表内置的sort()方法排序,也可以用Python内置的全局函数sorted()对可迭代的列表对象进行排序,从而生成新的列表。

使用列表的内置方法sort()对列表排序会“伤筋动骨”,修改列表本身的数据。而全局内置函数sorted()则不同,它会复制原始列表的一个副本,然后在副本上进行排序操作,在排序后,原始列表依旧“安然无恙”(参考Out[3]处的输出)。我们可以根据自己的需要来选择更适用于自己问题场景的方法。

列表中还有很多功能强大的内置方法,我们可以用dir(list)命令列举出来,具体用法读者可以自行查阅,我们会在后续的范例中逐步使用这些方法。

2.2.4.5 全局内置函数对列表的操作

除了列表这个数据类型本身自带的函数,Python的内置函数(可理解为脱离具体对象的全局函数)也可以对列表进行操作。部分函数如表2-2所示。

表2-2 部分Python内置函数对列表的操作

①随后,我们会介绍元组的概念。

由于表2-2中的大部分函数都能见名知意,且使用起来很简单,因此不过多介绍,下面我们主要介绍最后两个函数的使用方法。

先说明zip()的用法。我们先构建一个名为fruits的列表,它里面有7个元素,然后用内置函数len()获取列表的长度(即7),接着以该长度作为内置函数range()的参数,返回一个可迭代的序列[0, 1, 2, 3, 4, 5, 6]。

zip一词本身就有“拉链”的含义,事实上,zip()的功能就是把两个列表按照“丁对丁,卯对卯”模式,一一对应缝合起来,这样一来,每对“丁-卯”就形成了一个小元组(可理解为常量版的列表),多个小元组汇集在一起,就构成了一个新的列表,其工作流程如图2-5所示在“缝合”过程中,如果两个列表长度不一样该怎么样办呢?zip()会根据较短列表的长度,实施最大限度的“缝合”。

图2-5 zip()函数的工作流程

下面我们再说明enumerate()和列表之间如何联合使用。在Python中,enumerate()函数用于将可迭代的数据对象(如列表、元组或字符串等)组合为一个序列,同时列出数据和该数据的下标索引,形成一个个小元组。enumerate()方法的原型如下。

参数说明:sequence表示一个序列、迭代器或其他支持迭代对象;start表示下标起始位置。返回值为enumerate(枚举)对象。示例代码如下。

从上述两个例子来看,zip()和enumerate()实现的功能好像差不多,但其实不然。zip()能完成任意两个或多个不同类型的列表的“缝合”,适用面更广。而enumerate()只能为可迭代的序列(如列表、迭代器等)提供数值类型的索引封装,例如,在In [4]处为列表seasons的第1个元素'Spring'分配的索引值为0,为第2个元素'Summer'分配的索引值为1,以此类推。

其实,enumerate()的索引起始值是可以设定的,例如在In [7]处,把索引起始值start设置为1,那么第1个元素'Spring'的索引值则为1,第2个元素'Summer'的索引值为2,以此类推。

除能为列表服务之外,事实上,enumerate()函数还适用于元组或字符串等其他可迭代的数据对象,可将这些数据对象组合为一系列的(索引,元素)对,通常用在for循环当中。

本节我们简要地讨论了列表的用法,下面我们来讨论一下它的“孪生兄弟”——元组。

2.2.5 元组(Tuple)

法国启蒙思想家孟德斯鸠(Montesquieu)在其著作《论法的精神》中,提出一句名言:“一切有权力的人都容易滥用权力,这是万古不变的一条经验。”

或许由于Python的设计者们觉得列表的“权力”过大,过于“随心所欲”,于是就发明了它的孪生兄弟——元组。元组与列表非常相似,同样可以用索引访问,也同样可以嵌套。不同之处仅在于,元组中的元素一旦创建,便不能修改,它有点像常量版本的列表。故此,也有人将其称为“带上枷锁的列表”。

不同于列表的标识(一对方括号[]),元组使用一对圆括号“()”将元素囊括其中。创建元组非常简单,只需要在圆括号中添加元素,并用逗号将元素隔开即可。代码如下所示。

如果元组中只包含一个元素,则需要在元素后面添加逗号,代码如下所示。

在上述代码的In [3]处,如果我们忘记了第一个元素后面的“宝贵”逗号,会怎么样呢?请看下面的程序。

从上面Out[6]处的输出可以看出,编译器把In [5]处的tup1当作一个整型对象了,100的外围括号()仅仅是一个摆设。由此可见,对于元组而言,逗号甚至比圆括号()更具有身份象征意义。

有时,甚至去掉圆括号(),而仅仅保留逗号,也能定义一个元组,代码如下所示。

对元组的操作与列表类似,下标索引也是从0开始的,也可以进行分片操作等。

需要注意的是,元组的分片操作会临时产生一个新的元组,它不会更改原先的元组。

同样,我们可以用加号(+)操作符连接两个或多个元组,返回一个新的元组,代码如下所示。

元组和其他序列对象(如列表、字符串等)是可以相互转换的,代码如下所示。

由于元组的“常量”属性,其内部元素的值一旦确定下来,便无法修改,示例代码如下。

上面的错误信息明确告诉我们,元组内的元素是不支持修改的。但有时候一定要修改元组,这时该怎么办呢?可以通过迂回的“曲线救国”策略来完成,请参考如下代码。

从上面的代码中可以看出,至少在表面上,原本牢不可变的元组tup4中插入了一个新的元素“zhangsan”。插入工作是这样完成的:在输入行In [24]处,先通过元组分片技术,以第2个元素为基点,将原始元组拆分为两个部分tup4[:2]和tup4[2:];然后在中间插入一个("zhangsan",)。

对于多个不同元组的连接,通过加法操作符(+)可以完成。此时,Python解释器会生成一个新元组(即开辟了新的内存空间),然后将原来的变量名(tup4)指向这个连接好的新元组,旧的同名元组被销毁。

再次强调的是,新插入元素外的那对圆括号不可少,而其内部的逗号更不可少,因为它不仅是与后续元素之间的分隔符,还是一个元组的核心标志。也就是说,在In [24]处,实际上完成了三个元组的拼接。

这个手法姑且称为“狸猫换太子”,因为此tup4已非彼tup4。我们可以通过获取对象地址的内置函数id()来查看前后tup4的地址,对比输出行Out[23]和Out[25]给出的结果,可以发现,二者的地址(可理解为标识对象存在的身份证号码)完全不同,虽然对外宣示的名称都是tup4,但在Python底层,它们早已“物是人非”。

显然,我们也可以通过这种迂回的方式来删除元组中的数据。这个操作就交给“爱折腾、爱进步”的你来完成吧!在“浮光掠影”一般地讨论了元组之后,下面我们来讨论另外一种可变数据类型——字典。

2.2.6 字典(Dictionary)

在中国古代,字典被称为“字书”,直到《康熙字典》问世,才称“字典”。在字典里,为了检索方便,每个字都是独一无二的,而解释部分则比较随意。

借鉴这个结构,在编程语言中,也有“字典”这样的数据类型,它是由多个“键(key)/值(value)对”构成的。为了区分,每个“键”都必须是“独一无二”的,而“值”就好比字典的“解释部分”,内容随意。

在Python中,字典可被视为一种可变容器模型,能存储任意类型的对象,它是一种非常实用的数据类型,特别是在数据处理任务中,应用非常广泛。

在语法细节上,字典中的每个键/值对之间都用冒号(:)分隔开,不同的键/值对用逗号(,)分隔,整个字典包括在花括号({})之中,格式如下所示我们用比较形象的小贴士来辅助记忆列表、元组和字典这三者的不同。列表:“列”向量用[ ],方括号如同垂直站岗的队列。元组:“元”音同于圆,可以联想到圆括号( )。字典:“字”的上偏旁——宝盖头,将其竖立即为{ }。

字典中的“键”有点类似于我们的身份证号码,它必须独一无二,但“值”则不必受此约束,可同可不同。但不同于身份证号码的地方是,我们的身份证号码类型要保持一致,比如说,统一由18位整型或字符型混合而成,而Python字典中的“键”只要保证是“独一无二”的即可,具体是什么类型不做强制要求。它可以是数字、字符串,甚至是其他数据类型,如列表、字典等。如下所示的字典示例都是合法的。

在上述字典dict1中,包括三组“键/值对”,其中这三个“键”分别为字符串'a'、'2020'和数字100,它们彼此是可区分的,因此也就具备独一无二的特性,故都是合法有效的。三个“值”分别为1(数字)、[1,2,3](列表)和('hello','world')(元组)。

下面我们列举一个简单的示例说明字典的用法。

除了通过上述方式显示字典内容,还可以通过items()、keys()和values()等方法,分别显示字典的所有元素(即键/值对)、所有的键和所有的值,代码如下所示。

如果我们仅想输出字典中某个键对应的值,该怎么办呢?方法很简单,仅需要把键当作索引,放置于方括号[]之中,即可读取出来。

需要注意的是,在In [6]处,方括号[]中的数字100并不是数组的索引值,虽然它们看起来很像,但它仅仅是字典里的一个键,不过是长着一副整型数字的面孔罢了。如果我们想获得键为'a'的值,做类似的操作即可达成目的。

当然,我们也可以利用字典中的get()方法,提取给定键对应的值,如果键不在字典中,就返回默认值。如果不显式设定默认值,就返回None。总之,get()方法一定会返回一个值,让程序不报错。该方法的原型如下。

应用get()方法的示例代码如下所示。

因为字典属于可变的数据类型,因此如果我们想修改某个字典元素的值,是容易做到的,仅仅对某个给定“键”对应的元素,进行二次赋值即可。

如果我们想为字典添加一个元素,该怎么办呢?方法并不复杂,直接在字典中用方括号[]给出新的键,并赋值即可,代码如下所示。

我们还可以利用update()方法,将一个字典整体更新(添加)到另一个字典中,这个操作相当于列表或元组的连接(+)操作,示例代码如下。

如果我们想删除某个键对应的字典元素,可以使用pop()将其弹出。

前面的pop()方法通过“指名道姓”(特定“键”)的方式将字典中某个特定元素删除。其实,还有一种可匿名将字典最后一个元素弹出的方法,就是popitem(),其返回值是一个键/值对,它按照栈(stack)的数据结构,依据LIFO(Last In First Out,后进先出)规则,将字典最末尾的键/值对弹出(实际上也是一种删除操作),示例代码如下。

在讨论完字典之后,下面我们简单介绍和字典长得很像的另外一种数据类型,它就是集合。

2.2.7 集合(Set)

与其他编程语言类似,在Python中,集合是一个无序的元素集。正因为它无序,所以我们无法像访问列表一样,通过数字索引来访问集合中的元素。在形式上,集合与字典有类似之处,集合中的所有元素也是被花括号{}括起来的,元素之间用逗号分隔。

与字典的差别在于,字典中的每个元素都是用冒号隔开的键/值对,而集合中的元素只用普通的逗号分隔。

对比而言,集合中的元素都是孤立的,且是唯一的。也就是说,同一个集合中的元素不能重复,即使强制元素重复,集合本身也会自动去重,示例代码如下所示。

此外,也可以使用Python的内置函数set(),将列表和元组等其他可迭代的对象,转换为集合对象。如果原来的列表或元组中有重复元素,则在转换过程中,仅保留一个便可以达到“去重”效果。示例代码如下。

需要注意的是,集合中的元素只能包括数值、字符串、元组等不可变元素(可视为常量),不能包括列表、字典和集合等可变类型元素。

集合支持一系列标准操作,包括求并集(Union)、求交集(Intersection)等数学运算。示例代码如下。

集合同样也支持求差集(Difference)和求对称差集(Symmetric Difference)操作。

除了用减号(-)实现差集功能,也可以用特定方法,In [13]处可使用a_set.difference(b_set)得到同样的结果。

对称差集也可以使用特定方法来求得,In [14]处使用a_set.symmetric_difference(b_set)完全可以得到同样的结果。