组合数据类型

计算机不仅能对单个变量表示的数据进行处理, 通常情况, 计算机更需要对一组数据进行批量处理。这种能够表示多个数据的类型称为组合数据类型。

Python语言中最常用的组合数据类型有3大类,分别是集合类型、序列类型和映射类型。

集合类型

Python语言中的集合类型与数学中的集合概念一致, 即包含0个或多个数据项的无序组合。集合中的元素不可重复, 元素类型只能是不可变数据类型, 例如整数、浮点数、字符串、元组等。

相比较而言,列表、字典和集合类型本身都是可变数据类型,不能作为集合的元素出现。

Python语言中的集合是元素的无序组合, 其类型用大括号{}表示, 它没有索引和位置的概念, 集合中的元素可以动态增加或删除。

集合中的元素不可重复, 元素类型只能是固定数据类型, 而列表、字典和集合类型本身都是可变数据类型, 所以不能作为集合的元素出现。

type()函数返回的集合类型标记为set

1
2
3
4
s = {1010,1010,"78",19.5}
print(type(s)) #<class 'set'>
print(s) #{1010, 19.5, '78'}
print(len(s)) #3

需要注意的是, 由于集合中元素是无序的, 集合的输出顺序与定义顺序可以不一致。

由于集合元素独一无二, 使用集合类型能够过滤掉重复元素。

集合的创建

创建集合类型有两种方式: 用set()函数创建和直接赋初值创建。

set(x)函数可以根据参数x创建集合类型,要求参数x是组合数据类型,如列表或字符串等。如果参数x中存在重复元素,创建后的集合会去重。空集合用set()表示。

1
2
3
4
5
6
T = set([10,11,12,12,13])
print(T) #{10, 11, 12, 13}
T2 = set("123123")
print(T2) #{'1', '2', '3'}
T3 = set()
print(T3) #set()

赋初值方法利用大括号{}创建集合。需要注意 ,由于集合和字典类型都用大括号标记, 采用大括号方式创建集合时, 必须赋初值, 不能创建空集合。

1
2
3
4
5
6
7
T = {10,11,12,12,13}
print(T) #{10, 11, 12, 13}
T2 = {"123123"}
print(T2) #{'123123'}
T3 = {}
print(T3) #{}
print(type(T3)) #<class 'dict'> 字典类型

我们可以发现,T2使用函数创建和使用赋初值创建,打印输出的结果式不一样的。

因为set()函数只接收1个参数,因此会分解该参数,形成集合。而{}可以接收多个参数,每个参数会被当作一个独立元素,不会再被分解。

集合的操作

操作符

上述操作符表达了集合类型的4种基本操作, 交集(&)、并集(|)、差集(-)、补集(^), 操作逻辑与数学定义相同。

交并差补的运算:

1
2
3
4
5
6
S = {1010,"1010",78.9,1010,12.3}
T = {1010,"1010",13}
print(S-T) #{12.3, 78.9}
print(S|T) #{1010, 13, 12.3, '1010', 78.9}
print(S&T) #{1010, '1010'}
print(S^T) #{12.3, 13, 78.9}

操作函数

简单写一下函数的使用

1
2
3
4
5
6
7
8
9
S = {1010,"1010",12.3}
S.add(1) #添加元素
print(S) #{'1010', 1, 1010, 12.3}
S.remove(12.3) #删除元素
print(S) #{'1010', 1010, 1}
print(len(S)) #3
print(1010 in S)#True
S.clear() #移除所有数据
print(S) #set()

序列类型

序列类型是一维元素向量, 元素之间存在先后关系, 通过序号访问, 元素之间不排他。

由于元素之间存在顺序关系, 所以序列中可以存在数值相同但位置不同的元素。 Python语言提供了多种序列数据类型, 其中比较重要的是字符串类型、列表类型和元组类型。

字符串类型可以看成是单一字符的有序组合, 属于序列类型。

元组和列表是可以使用多种类型元素的序列类型

注意:序列类型使用相同的索引体系,即正向递增序号和反向递减序号

序列类型有一些通用的操作符和函数

操作符 描述
in x in s,如果 x 是 s 的元素,返回 True;否则返回 False
not in x not in s,如果 x 不是 s 的元素,返回 True;否则返回 False
+ s+t,连接s和t
* s*n或n*s,将序列 s 复制 n 次
s[i] 索引, 返回序列的第 i 个元素
s[i:j] 切片,返回包含序列 s 第 i 到 j 个元素的子序列(不包含第 j 个元素)
s[i:j:k] 步骤切片,返回包含序列 s 第 i 到 j 个元素以 k 为步数的子序列
len(s) 序列 s 的元素个数(长度)
min(s) 序列 s 中的最小元素
max(s) 序列 s 中的最大元素
s.index(x) 序列s中第一次出现元素 x 的位置
s.count(x) 序列s中出现 x 的总次数

列表的定义

列表是包含0个或多个元素的有序序列, 属于序列类型。

列表可以进行元素增加、删除、替换、查找等操作。

列表没有长度限制,元素类型可以不同,不需要预定义长度。

列表类型用中括号[]表示,也可以通过list(x)函数将集合或字符串类型转换成列表类型。list()函数可生成空列表

1
2
3
4
5
6
s = ['1010',1010,1010,[1010,"1010"]]
print(s) #['1010', 1010, 1010, [1010, '1010']]
s2 = list("你好啊")
print(s2) #['你', '好', '啊']
s3 = list()
print(s3) #[]

因为列表属于序列类型,也可以使用序列类型的操作符和函数

1
2
3
4
5
6
7
s = ['1010',1010,1010,[1010,"1010"]]
t = [123,456]
print(1010 in s) #True
print(s+t) #['1010', 1010, 1010, [1010, '1010'], 123, 456]
print(t*2) #[123, 456, 123, 456]
print(s.index(1010))#1
print(s.count(1010))#2

列表的索引

索引是列表的基本操作, 用于获得列表中的一个元素。

该操作沿用序列类型的索引方式, 即正向递增序号或反向递减序号 ,使用中括号作为索引操作符, 索引序号不能超过列表的元素范围, 否则会产生 Index Error错误。

1
2
3
4
s = ['1010',1010,1010,[1010,"1010"]]
print(s[1]) #1010
print(s[-1]) #[1010, '1010']
print(s[10]) #IndexError报错

可以使用遍历循环对列表元素进行遍历

1
2
3
s = ['1010',1010,1010,[1010,"1010"]]
for i in s:
print(i)

列表的切片

切片是列表的基本操作, 用于获得列表的一个片段, 即获得零个或多个元素。

切片后的结果也是列表类型。

切片有两种使用方式:

1
2
3
<列表或列表变量>[N:M]
#或
<列表或列表变量>[N:M:K]

切片获取列表类型从 N 到 M (不包含M)的元素组成新的列表, 其中, N 和 M 为列表类型的索引序号,可以混合使用正向递增序号和反向递减序号, 一般要求N小于M。

当N大于等于M时, 返回空列表。

当K存在时, 切片获取列表类型从 N 到 M (不包含M)以K为步长所对应元素组成的列表。

1
2
3
4
5
s = ['1010',1010,1010,[1010,"1010"]]
print(s[1:3]) #[1010, 1010]
print(s[-1:-3]) #[]
print(s[-3:-1]) #[1010, 1010]
print(s[0:3:2]) #['1010', 1010]

列表类型的操作

操作函数

len()函数

len(ls)获取一个列表的元素个数, 即长度。

1
2
s = ['1010',1010,1010,[1010,"1010"]]
print(len(s)) #4
max()和min()函数

min(ls) 和 max(ls)分别返回一个列表的最小或最大元素, 使用这两个函数的前提是列表中各元素类型可以进行比较。如果列表元素间不能比较, 使用这两个函数将会报错。

1
2
3
4
5
s = [1010,2222,10]
print(min(s)) #10
print(max(s)) #2222
s2 = ['1010',1010,1010,[1010,"1010"]]
print(min(s2)) #TypeError报错
list()函数

list(x)将变量 x 转变成列表类型,其中x可以是字符串类型,也可以是字典类型

1
2
3
print(list("Hello"))		#['H', 'e', 'l', 'l', 'o']
print(list({"我","爱","你"}))#['我','爱','你' ]
print(list({"1":"小明","2":'小红'}))#['1', '2']

操作方法

append()

ls.append(x)在列表ls的最后增加一个元素x

1
2
3
ls = [1010,"1010"]
ls.append(123)
print(ls) #[1010, '1010', 123]
insert()

ls.insert(i,x)在列表ls中序号i位置上增加元素x, 序号i之后的元素序号依次增加。

1
2
3
ls = [1010,"1010"]
ls.insert(1,123)
print(ls) #[1010, 123, '1010']
clear()

Is.clear()将列表ls的所有元素删除, 清空列表。

1
2
3
ls = [1010,"1010"]
ls.clear()
print(ls) #[]
pop()

ls.pop(i)将返回列表ls中序号为i的元素, 并将该元素从列表中删除。

1
2
3
ls = [1010,"1010",12.3]
ls.pop(2)
print(ls) #[1010, '1010']
remove()

Is.remove(x)将删除列表ls中第一次出现的x元素。

1
2
3
ls = [1010,"1010",12.3]
ls.remove(1010)
print(ls) #['1010', 12.3]

当然除了用remove()删除元素,还可以使用 Python保留字del对列表元素或片段进行删除

1
2
3
4
5
del <列表变量><索引序号>
#或
del <列表变量>[<索引起始>:<索引结束>]
#或
del <列表变量>[<索引起始>:<索引结束>:<步长>]
1
2
3
4
5
6
7
8
9
10
11
ls = [1010,"1010",12.3,1111,1234,5678]
del ls[1]
print(ls) #[1010, 12.3, 1111, 1234, 5678]

ls = [1010,"1010",12.3,1111,1234,5678]
del ls[1:3]
print(ls) #[1010, 1111, 1234, 5678]

ls = [1010,"1010",12.3,1111,1234,5678]
del ls[::2]
print(ls) #['1010', 1111, 5678]
reverse()

Is.reverse()将列表ls中的元素进行逆序反转。

1
2
3
ls = [1010,"1010",12.3,1111,1234,5678]
ls.reverse()
print(ls) #[5678, 1234, 1111, 12.3, '1010', 1010]
copy()

ls.copy()复制ls中所有元素生成一个新列表。

1
2
3
4
ls = [1010,"1010",12.3]
lt = ls.copy()
ls.clear()
print(lt) #[1010, '1010', 12.3]

由上例看出, 列表ls使用copy()方法复制后赋值给变量lt, 将ls元素清空不影响新生成的变量lt

如果不使用copy()方法, 通过直接赋值方式是不能产生新列表的,仅能够为列表增加一个别名

1
2
3
4
ls = [1010,"1010",12.3]
lt = ls
ls.clear()
print(lt) #[]

注意:对于基本的数据类型, 如整数或字符串, 可以通过等号实现元素赋值。

但对于列表类型, 使用等号无法实现真正的赋值。其中, lt=ls语句并不是拷贝Is中元素给变量lt, 而是新关联了一个引用, lsIt所指向的是同一套内容

1
2
3
4
5
ls = [1010,"1010",12.3]
a = 1
ls[1] = a
a = 2
print(ls) #[1010, 1, 12.3]

使用切片配合等号=可以对列表片段进行修改,修改内容可以不等长。当使用一个列表改变另一个列表值时, Python不要求两个列表长度一样, 但遵循“多增少减”的原则。

1
2
3
4
5
ls = [1010,"1010",12.3]
ls[0:2] = [1111,"111",123]
print(ls) #[1111, '111', 123, 12.3]
ls[1:3] = [5]
print(ls) #[1111, 5, 12.3]

元组类型

元组类型与列表类型相似, 都是序列类型。

元组类型在 Python语言中表示为 tuple, 一般使用小括号和逗号

1
2
t = (1,2,3)
print(type(t)) #<class 'tuple'>

元组类型一旦定义就不能修改, 在编程中不够灵活, 同时, 元组类型的所有操作都可以由列表类型实现, 因此, 一般编程中, 如果需要自定义变量, 通常以列表类型替代元组类型使用。

如果确认编程中不需要修改数据,可以使用元组类型。

元组类型主要在 Python语法相关的场景使用例如, 当函数返回多个值时, 多个返回值以元组类型返回, 实际上返回一个数据类型。

1
2
3
4
def f(x):
return x,x+1,x+2
print(f(1)) #(1, 2, 3)
print(type(f(1))) #<class 'tuple'>

映射类型

映射类型是“键-值”数据项的组合, 每个元素是一个键值对, 表示为(key, value), 元素之间是无序的。

键值对(key, value)是一种二元关系, 源于属性和值的映射关系。

键(key)表示一个属性, 也可以理解为一个类别或项目,

值(value)是属性的内容, 键值对刻画了一个属性和它的值。键值对将映射关系结构化,用于存储和表达。

映射类型是序列类型的一种扩展。在序列类型中,采用从0开始的正向递增序号进行具体元素值的索引。而映射类型则由用户来定义序号, 即键, 用其去索引具体的值。键值对的概念在计算机系统中十分常见,也是表达和存储数据的常见方式。

Python语言提供了专门的映射类型,即字典类型。

字典类型定义

Python语言中的字典使用大括号{}建立, 每个元素是一个键值对

1
{<键1>:<值1>,<键2>:<值2>,…,<键n>:<值n>}

其中, 键和值通过英文冒号连接, 不同键值对通过英文逗号隔开。

从 Python设计角度考虑由于大括号{}可以表示集合

所以, 字典类型也具有和集合类似的性质, 即键值对之间没有顺序且不能重复。可以简单地把字典看成元素是键值对的集合。

注意, 尽管都使用大括号, 但集合与字典是不同的类型。

1
2
d = {"1":"小明","2":"小红","3":"小美"}
print(d) #{'1': '小明', '2': '小红', '3': '小美'}

字典的索引

索引是按照一定顺序检索内容的体系。列表类型采用元素顺序的位置进行索引。由于字典元素“键值对”中键是值的索引,因此,可以直接利用键值对关系索引元素。

1
<值>=<字典变量>[<键>]

采用大括号可以直接建立字典。

1
2
d = {"1":"小明","2":"小红","3":"小美"}
print(d["2"]) #小红

利用索引和赋值=配合,可以对字典中每个元素进行修改。

1
2
3
d = {"1":"小明","2":"小红","3":"小美"}
d["2"] = "小小红"
print(d) #{'1': '小明', '2': '小小红', '3': '小美'}

使用大括号可以创建字典, 可以创建一个空字典。通过索引和赋值配合, 可以向字典中增加元素。

1
2
3
d = {}
d["1"] = "小红"
print(d) #{'1': '小红'}

字典类型的操作

操作函数

len()函数

len(d)给出字典d的元素个数,也称为长度。

1
2
d = {"1":"小明","2":"小红","3":"小美"}
print(len(d)) #3
min()和max()函数

min(d)和max(d)分别返回字典d中最小或最大索引值, 使用这两个函数的前提是字典中各索引元素可以进行比较。

1
2
3
d = {"1":"小明","2":"小红","3":"小美"}
print(min(d)) #1
print(max(d)) #3
dict()函数

dict()函数用于生成一个空字典, 作用和相同。

1
2
d = dict()
print(d) #{}

操作方法

字典类型存在一些操作方法

1
<字典变量>.<方法名称>(<方法参数>)
key()

d.keys()返回字典中的所有键信息, 返回结果是 Python的一种内部数据类型 dict_keys,专用于表示字典的键。如果希望更好地使用返回结果, 可以将其转换为列表类型。

1
2
3
4
d = {"1":"小明","2":"小红","3":"小美"}
print(d.keys()) #dict_keys(['1', '2', '3'])
print(type(d.keys())) #<class 'dict_keys'>
print(list(d.keys())) #['1', '2', '3']
values()

d.values()返回字典中的所有值信息, 返回结果是 Python的一种内部数据类型 dict_values。如果希望更好地使用返回结果, 可以将其转换为列表类型。

1
2
3
4
d = {"1":"小明","2":"小红","3":"小美"}
print(d.values()) #dict_values(['小明', '小红', '小美'])
print(type(d.values())) #<class 'dict_values'>
print(list(d.values())) #['小明', '小红', '小美']
items()

d.items()返回字典中的所有键值对信息, 返回结果是 Python的一种内部数据类型dict_items。如果希望更好地使用返回结果, 可以将其转换为列表类型, 键值对以元组类型(即括号形式)表示。

1
2
3
4
d = {"1":"小明","2":"小红","3":"小美"}
print(d.items()) #dict_items([('1', '小明'), ('2', '小红'), ('3', '小美')])
print(type(d.items())) #<class 'dict_items'>
print(list(d.items())) #[('1', '小明'), ('2', '小红'), ('3', '小美')]
get()

d.get(key, default)根据键信息查找并返回值信息, 如果key存在则返回相应值, 否则返回默认值, 第二个元素 default可以省略,如果省略则默认值为空。

1
2
3
4
d = {"1":"小明","2":"小红","3":"小美"}
print(d.get("2")) #小红
print(d.get("4")) #None
print(d.get("4","木有"))#木有
pop()

d.pop(key, default)根据键信息查找并取出值信息 ,如果key存在则返回相应值, 否则返回默认值, 第二个元素 default可以省略, 如果省略则默认值为空。相比d.get()方法, d.pop()在取出相应值后, 将从字典中删除对应的键值对。

1
2
3
d = {"1":"小明","2":"小红","3":"小美"}
print(d.pop("2")) #小红
print(d) #{'1': '小明', '3': '小美'}
popitem()

d.popitemo随机从字典中取出一个键值对, 以元组(key, value)形式返回。取出后从字典中删除这个键值对。

1
2
3
4
d = {"1":"小明","2":"小红","3":"小美"}
a = d.popitem()
print(a)
print(d)
clear()

d.clear删除字典中所有键值对。

1
2
3
d = {"1":"小明","2":"小红","3":"小美"}
d.clear()
print(d) #{}

此外, 如果希望删除字典中某一个元素, 可以使用 Python保留字del

1
2
3
d = {"1":"小明","2":"小红","3":"小美"}
del d["1"]
print(d) #{'2': '小红', '3': '小美'}

字典类型也支持保留字in, 用来判断一个键是否在字典中。如果在, 则返回True, 否则返回False。

1
2
3
d = {"1":"小明","2":"小红","3":"小美"}
print("1" in d) #True
print("4" in d) #False

与其他组合类型一样,字典可以遍历循环对其元素进行遍历

1
2
for <变量名> in <字典名> :
语句块

由于键值对中的键相当于索引, 所以, for循环返回的变量名是字典的索引值。如果需要获得键对应的值, 可以在语句块中通过get()方法获得。

1
2
3
4
5
6
d = {"1":"小明","2":"小红","3":"小美"}
for k in d:
print("字典的值和键分别是{}和{}".format(k,d.get(k)))
# 字典的值和键分别是1和小明
# 字典的值和键分别是2和小红
# 字典的值和键分别是3和小美