Python组合数据类型¶
约 4635 个字 318 行代码 预计阅读时间 19 分钟
序列¶
在Python中,有一些结构,它们的元素是有序排列的,并且可以通过下标访问成员,这些结构统称为序列,这些结构有如下几种:
- 列表
range- 元组
- 字符串
对于序列来说,有下面通用的函数:
len(序列):获取指定序列的元素个数del(序列):释放指定序列的内存空间,并将对应的引用删除max(序列):获取指定序列中的最大元素min(序列):获取指定序列中的最小元素sum(序列):获取指定序列中的元素总和
Note
- 需要注意,对于列表和元组来说,因为其可以存储各种类型,所以对于
max、min、sum函数来说,如果列表和元组存储的是各种类型,则无法取出最大元素和最小元素 - 使用
del语句可以删除变量与它所关联的对象之间的链接。这不会删除内存中的对象本身,除非这是对该对象的最后一份引用。删除后,尝试访问被删除的变量会导致错误
对于组合数据类型来说,有下面通用的操作:
+(序列+序列):表示合并两个序列,其支持的序列有:字符串、列表、元组*(序列*序列):表示重复指定次数序列中的元素,其支持的序列有:字符串、列表、元组in:判断指定元素是否在指定序列中,其支持的结构有:字符串、列表、元组、字典not in:判断指定元素是否不在指定序列中,其支持的结构有:字符串、列表、元组、字典>、>=、==、<、<=:一一比较序列中的元素,其支持的结构有:字符串、列表、元组
可变序列和不可变序列¶
可变序列(Mutable Sequences)
定义:可变序列是指其内容可以在创建后被修改的序列类型。你可以添加、删除或更改序列中的元素
常见的可变序列类型:
- 列表(list)
- 字节数组(bytearray)
特点:
动态大小:可以动态地添加或删除元素 支持多种操作:如append()、extend()、insert()、remove()、pop()等方法 内存效率:由于可以修改,内存分配更加灵活
不可变序列(Immutable Sequences)
定义:不可变序列是指其内容一旦创建后就不能被修改的序列类型。任何修改操作都会创建一个新的序列
常见的不可变序列类型:
- 元组(tuple)
- 字符串(str)
- 范围对象(range)
特点:
- 固定大小:创建后大小不可更改
- 安全性:由于不可变,适合用于作为字典的键或集合的元素
- 性能优化:Python对不可变对象可以进行内部优化,如字符串驻留(interning)
表格比较:
| 特性 | 可变序列(Mutable) | 不可变序列(Immutable) |
|---|---|---|
| 修改内容 | 可以直接修改、添加、删除元素 | 一旦创建后内容不能修改 |
| 常见类型 | list,bytearray | tuple,str,range |
| 内存分配 | 动态分配,灵活 | 固定分配,内存优化 |
| 使用场景 | 需要频繁修改数据时使用 | 数据不变或需要作为字典键时使用 |
| 方法支持 | 丰富的修改方法,如append | 仅支持查询和访问方法 |
| 安全性 | 较低,可能引入数据一致性问题 | 较高,数据更加稳定和安全 |
选择:
使用可变序列:
当需要频繁修改数据,如添加、删除或更改元素时。例如,维护一个动态更新的列表,如任务列表、购物清单等
使用不可变序列:
当数据不需要修改,或需要作为字典的键、集合的元素时。例如,记录固定的配置参数、存储不变的数据记录等
列表¶
基本使用¶
List(列表)是Python中使用最频繁的数据类型,类似于C++中的vector、Java中的ArrayList和JavaScript中的数组
在Python中,使用[]定义列表,例如下面的代码:
| Python | |
|---|---|
1 2 | |
除了上面的方式定义空列表,还可以使用强制转换函数list()创建一个空列表,list()函数实际作用是将可迭代对象转换为列表对象,例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 | |
因为列表属于序列结构,所以可以使用索引(下标)访问,需要注意,如果下标(正数和负数)超出了列表的长度,则会报错为越界访问
列表的基本使用如下:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
遍历列表¶
前面提到for-in可以对可迭代对象进行遍历,而序列都属于可迭代对象,所以可以使用for-in进行遍历,例如下面的代码:
| Python | |
|---|---|
1 2 3 4 | |
除了上面使用for-in+指定序列以外,还可以使用for-in+enumerate(序列),此时就可以同时获取到元素和对应的下标,例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
如果需要使用下标遍历列表,则可以使用下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
列表常用方法¶
因为是方法,所以需要列表对象进行调用,常用方法如下:
append(元素):向列表尾部插入一个元素,返回Nonepop(下标):删除指定下标的元素,返回删除的元素,其参数可以不传递,默认删除最后一个元素insert(下标, 元素):在指定下标位置插入一个元素,返回Noneextend(可迭代对象):在列表尾部插入可迭代对象中的内容copy():拷贝对象列表,返回一个拷贝后的列表index(元素,起始位置,终止位置):在指定区域内查找一个元素,如果存在返回其下标,否则报错,该方法有三个参数,分别表示待查找的元素、查找区间的起始位置(包括,默认是从0索引开始)和查找区间的终止位置(不包括,默认为列表的最后一个元素位置)。如果列表中存在重复元素,则只会返回正向遍历下第一个元素的下标remove(元素):删除指定元素,如果有多个只会删除正向遍历的第一个,返回Nonecount(元素):统计指定元素的个数,返回元素个数,如果元素不存在,则返回0clear():清空列表,返回Nonesort(比较函数, 是否降序):排序(默认升序)列表中的元素,返回None,该方法有两个参数,分别表示列表元素的比较方式函数和是否降序标识(默认为false,即表示升序)reverse():反转列表,返回None
Note
- 根据官方文档的描述,
sort()函数利用的是稳定排序 copy方法是浅拷贝,如果想使用深拷贝,则可以考虑使用copy类中的deepcopy(对象)方法clear()方法不同于del()函数,del()函数会删除对应的引用变量,clear()只是清空元素,并不会删除列表对象本身
基本使用如下:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
列表推导式¶
列表推导式使得创建列表的方式更简洁,基本语法如下:
| Python | |
|---|---|
1 | |
其中:
expression:对每个元素执行的操作item:迭代变量,表示从iterable中取出的每个元素iterable:一个可迭代对象,如列表、元组、字符串等condition(可选):一个布尔表达式,用于过滤元素。只有当条件为True时,对应的expression才会被计算并添加到新列表中
例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
在上面的代码中,创建一个new_list列表,每一个元素是一个元组,根据两个可迭代对象[1,2,3]和[3,1,4],判断生成的x和y不相等时将x和y构成的元组插入到列表中
元组¶
基本使用¶
元组是一个与列表很像的序列,但是与列表不同的是,其元素在元组创建完成后不可以修改
在Python中,使用()定义元组,例如下面的代码:
| Python | |
|---|---|
1 2 | |
除了上面的方式定义空元组,还可以使用强制转换函数tuple()创建一个空元组,tuple()函数实际作用是将可迭代对象转换为元组对象,例如下面的代码:
| Python | |
|---|---|
1 2 3 4 | |
元组中的元素也可以通过下标进行访问,但是不可以通过下标进行修改,否则会报错
| Python | |
|---|---|
1 2 3 4 5 | |
因为序列的通用操作对于元组也生效,除了修改元组的操作以外,其他的操作使用方式与列表相似,所以此处不再演示
Note
尽管元组属于不可变序列,但是依旧可以使用+和*操作,此时会根据运算结果创建一个新元组而不会改变原来的元组
遍历元组¶
与列表一样,遍历元组可以采用三种方式:
for-in+元组for-in+enumerate(序列)- 下标遍历列表
使用方式与列表一致,不再演示
元组常用方法¶
因为元组中的元素不可以修改,所以方法比较少:
count(元素):统计元组中的元素个数,返回对应的元素出现的次数,如果不存在指定元素,则返回0index(元素):在指定区域内查找一个元素,如果存在返回其下标,否则报错,该方法有三个参数,分别表示待查找的元素、查找区间的起始位置(包括,默认是从0索引开始)和查找区间的终止位置(不包括,默认为列表的最后一个元素位置)。如果列表中存在重复元素,则只会返回正向遍历下第一个元素的下标
使用方式和列表类似,不再演示
range¶
在Python中,range是系统提供的内建函数,其原型为:range(start,end,[step=1]),表示根据起始位置(start)、终止位置(end)和步长(step)生成一个等差序列[start, end)。默认情况下,该函数的步长为1。如果传递的参数个数只有一个,则该函数表示从0开始遍历到end-1
Note
注意range生成的序列属于不可变序列,不支持元素修改,不支持+和*操作
在Python中,range一般用于for-in循环遍历,使用方式已经在前面演示过,本次不再演示
根据range的特点,可以写出下面两个等价的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 | |
Note
如果要指定步长,则必须要指定start参数
字符串其他介绍与常用方法¶
在Python中,字符串也属于序列,但是也属于不可变序列,即其中元素不可以进行修改。与元组一样,如果使用+和*,实际上是创建了一个运算后的新字符串,而并没有修改原来的字符串
由于字符串的不可变性,尽管字符串中提供了许多修改字符串的方法,实际上这些方法最后都会根据运算结果创建一个新的字符串并返回
基本使用和遍历与其他序列相同,此处不再介绍,下面主要介绍其方法:
-
is...系列:判断字符串的字符是否满足指定条件,如果满足,返回True,否则返回False,可以参考C语言中的字符函数,例如下面的方法:isascii():判断字符串中的字符是否是ASCII表中的字符isalnum():判断字符串中的字符是否是数字+英文字母组成isdigit():判断字符串中的字符是否都是数字字符isalpha():判断字符串中的字符是否都是英文字母islower():判断字符串中的字符是否都是小写字母isupper():判断字符串中的字符是否都是大写字母isprintable():判断字符串中的字符是否是可打印的字符
-
capitalize():将字符串首字符大写,返回一个新字符串 center(字符总个数, 用于填充的字符):将字符串中的内容用其他内容包裹在中间,使最后字符串长度为指定长度,注意,用于填充的字符长度只能为1,返回一个新字符串count(字符):统计字符串中指定字符的个数,返回个数值endswith(字符串):判断字符串是否以某一个字符串结尾,如果是,返回True,否则返回Falsestartswith(字符串):判断字符串是否以某一个字符串开头,如果是,返回True,否则返回Falsefind(字符串, 起始位置, 终止位置):在原字符串中查找子串,返回值为匹配的起始位置下标,如果找不到,返回-1index(字符串, 起始位置, 终止位置):在原字符串中查找子串,返回值为匹配的起始位置下标,如果找不到,报错分隔符字符串.join(原字符串):将原字符串的每个字符以分隔符字符串分隔,返回一个字符串replace(待替换的字符串, 用于替换的字符串, 个数):根据指定个数用新字符串替换原字符串中的指定字符串,返回一个新字符串split(分隔符字符串):根据指定字符串拆分原来的字符串,返回一个列表upper():将字符串中的字符全部切换为大写,返回一个新字符串lower():将字符串中的字符全部切换为小写,返回一个新字符串
基本使用如下:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
字典¶
基本使用¶
字典是Python中除了列表以外最灵活的类型,字典中一般存储的是键值对key-value
在Python中,使用{}定义字典,其中key为键,value为值,key和value使用:分隔。字典中的value可以是任意数据类型,但是key只能是字符串、数字或者元组,且key不可以重复,不同的键值对使用,进行分隔,最后一个键值对后可以不需要逗号
Note
因为字典底层是哈希表,而不是红黑树,所以插入的元素默认不会进行排序
同样,可以通过字典的强制类型转换函数dict()创建一个空字典
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
遍历字典¶
与序列遍历不同,因为字典存储的是键值对类型,所以遍历需要使用键访问到对应的值,需要先获取到键,再通过索引的方式访问到对应的值,例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
如果想直接拿到value,则可以使用字典中的方法values(),例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
如果想获取到所有的key,则可以使用字典中的方法keys(),例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
字典索引操作和常用方法¶
字典的索引操作和C++中的unordered_map索引操作非常类似,其有下面的功能:
- 索引(键)不存在且有赋值操作:插入新的键值对
- 索引(键)存在且有赋值操作:修改已有的键值对中的值
- 索引(键)存在但无赋值操作:取出键对应的值
Note
与C++的unordered_map不同,如果索引(键)不存在且没有赋值操作时,此时不会新增键,而是直接被视为根据键取值,因为当前键不存在,所以会直接报错
例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 | |
字典中的常用方法如下:
get(键, 键不存在时的返回值):通过键获取对应的值,与索引不同的是,如果键不存在,则本方法会默认返回None而不是触发KeyError,该方法有两个参数,第一个参数表示指定的key,第二个参数表示指定的key不存在时返回的内容,默认情况下为None。注意,本方法如果指定的键不存在时,不会将对应的键插入到原字典中pop(键):删除键对应的键值对,返回删除键对应的值,注意本方法没有默认删除情况popitem():删除最后一个插入到字典的键值对,并返回删除的键值对,注意本方法在字典为空时会触发KeyErrorsetdefault(键, 值):如果字典存在键key,返回它的值。如果不存在,插入第二个参数为指定值的键key,并返回该值。第二个参数默认为Noneupdate(键值对):更新字典中存在的键,如果键存在,则根据参数键值对的值覆盖字典对应的键值对的值,如果不存在更新的键值对,则插入该键值对
Note
对于popitem()方法来说,在3.7版本发生变更: 现在会确保采用LIFO顺序。 在之前的版本中,popitem()会返回一个任意的键/值对
例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
集合¶
基本使用¶
集合是与字典非常类似的数据结构,其底层也是哈希表,但是其插入的只有键(键与值相同)且键不可以重复
Python并没有为集合单独提供一种符号代表set,所以不可以使用{}等创建一个空集合,但是如果{}中元素,则可以使用{},如果需要创建一个空集合,则可以使用set的强制转换函数set()
Note
注意,如果将字典转换为集合,则集合中存储的只是字典的键
例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
遍历集合¶
集合的遍历与序列的遍历一致,此处不再演示
集合常用方法和操作¶
集合常用方法:
add(元素):向集合中插入元素update(可迭代对象):向集合中插入可迭代对象中的每个元素remove(元素):从集合中删除指定元素,如果元素不存在,则会触发KeyErrorclear:清空集合
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
集合的操作:
- 集合的交集:使用
&或者方法intersection(另一个或多个集合),返回交集集合 - 集合的并集:使用
|或者方法union(另一个或多个集合),返回并集集合 - 集合的差集:使用
-或者方法difference(另一个或多个集合),返回差集集合 - 集合的子集:使用
<=或者方法issubset(另一个集合),是子集返回True,否则返回False
例如下面的代码:
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |