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(元素)
:向列表尾部插入一个元素,返回None
pop(下标)
:删除指定下标的元素,返回删除的元素,其参数可以不传递,默认删除最后一个元素insert(下标, 元素)
:在指定下标位置插入一个元素,返回None
extend(可迭代对象)
:在列表尾部插入可迭代对象中的内容copy()
:拷贝对象列表,返回一个拷贝后的列表index(元素,起始位置,终止位置)
:在指定区域内查找一个元素,如果存在返回其下标,否则报错,该方法有三个参数,分别表示待查找的元素、查找区间的起始位置(包括,默认是从0索引开始)和查找区间的终止位置(不包括,默认为列表的最后一个元素位置)。如果列表中存在重复元素,则只会返回正向遍历下第一个元素的下标remove(元素)
:删除指定元素,如果有多个只会删除正向遍历的第一个,返回None
count(元素)
:统计指定元素的个数,返回元素个数,如果元素不存在,则返回0clear()
:清空列表,返回None
sort(比较函数, 是否降序)
:排序(默认升序)列表中的元素,返回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
,否则返回False
startswith(字符串)
:判断字符串是否以某一个字符串开头,如果是,返回True
,否则返回False
find(字符串, 起始位置, 终止位置)
:在原字符串中查找子串,返回值为匹配的起始位置下标,如果找不到,返回-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()
:删除最后一个插入到字典的键值对,并返回删除的键值对,注意本方法在字典为空时会触发KeyError
setdefault(键, 值)
:如果字典存在键key
,返回它的值。如果不存在,插入第二个参数为指定值的键key
,并返回该值。第二个参数默认为None
update(键值对)
:更新字典中存在的键,如果键存在,则根据参数键值对的值覆盖字典对应的键值对的值,如果不存在更新的键值对,则插入该键值对
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(元素)
:从集合中删除指定元素,如果元素不存在,则会触发KeyError
clear
:清空集合
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 |
|