第3章 列表、元组和字典
python内置的三种常见数据结构:列表(list)、元组(tuple)和字典(dict)。这三种数据结构都可用于保存多个数据项。
列表和元组比较相似,它们都按顺序保存元素,每个元素都有自己的索引,因此列表和元组都可通过索引访问元素。二者的区别在于列表是可修改的,元组不可修改。字典则以key-value的形式保存数据。
序列简介
序列:指的是一种包含多项数据的数据结构,序列包含的多个数据(也叫成员)按顺序排列,可通过索引访问成员。
Python的序列
Python的常见序列类型包括字符串、列表和元组等。
列表和元组最主要的区别:
- 元组是不可变的,元组一旦构建出来,程序就不能修改元组所包含的成员(就像字符串也是不可变的,程序无法修改字符串所包含的字符序列)
- 列表是可变的,程序可以修改列表所包含的元素
创建列表和元组
创建列表使用方括号[]、创建元组使用圆括号(),并在括号中列出元素,元素之间使用英文逗号隔开:
创建列表的语法格式:
[ele1,ele2,ele3,...]
创建元组的语法格式:
(ele1,ele2,ele3,...)
示例:
# 使用方括号定义列表
my_list = ['crazyit', 20, 'Python']
print(my_list)
# 使用圆括号定义元组
my_tuple = ('crazyit', 20, 'Python')
print(my_tuple)
输出结果:
['crazyit', 20, 'Python']
('crazyit', 20, 'Python')
列表和元组的通用用法
通过索引使用元素
列表和元组都可通过索引访问元素,它们的索引都是从0开始的,第1个元素的索引为0;也支持使用负数索引,倒数第1个元素的索引为-1,依次类推。
列表的元素相当于一个变量,程序即可使用它的值,也可对元素赋值;元组的元素相当于一个常量,程序只能使用它的值,不能对它重新赋值。
子序列
列表和元组可使用索引获取中间一段,这种用法被称为slice(分片或切片),slice的完整语法格式如下:
[start:end:step]
start、end两个索引值都可使用正数或负数,其中负数表示从倒数开始。该语法表示从start索引的元素开始(包含),到end索引的元素结束(不包含)的所有元素---这和所有编程语言的约定类似。step表示步长,因此step使用负数没有意义。
示例:
a_tuple = ('crazyit', 20, 5.6, 'fkit', -17)
# 访问从第2个到倒数第4个(不包含)所有元素
print(a_tuple[1: 3]) # (20, 5.6)
# 访问从倒数第3个到倒数第1个(不包含)所有元素
print(a_tuple[-3: -1]) # (5.6, 'fkit')
# 访问从第2个到倒数第2个(不包含)所有元素
print(a_tuple[1: -2]) # (20, 5.6)
# 访问从倒数第3个到第5个(不包含)所有元素
print(a_tuple[-3: 4]) # (5.6, 'fkit')
b_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9)
# 访问从第3个到第9个(不包含)、间隔为2的所有元素
print(b_tuple[2: 8: 2]) # (3, 5, 7)
# 访问从第3个到第9个(不包含)、间隔为3的所有元素
print(b_tuple[2: 8: 3]) # (3, 6)
# 访问从第3个到倒数第2个(不包含)、间隔为3的所有元素
print(b_tuple[2: -2: 2]) # (3, 5, 7)
输出结果:
(20, 5.6)
(5.6, 'fkit')
(20, 5.6)
(5.6, 'fkit')
(3, 5, 7)
(3, 6)
(3, 5, 7)
加法
列表和元组支持加法运算,加法的和就是两个列表或元组所包含的元素的总和。列表只能和列表相加;元组只能和元组相加;元组不能直接和列表相加。
示例:
a_tuple = ('crazyit' , 20, -1.2)
b_tuple = (127, 'crazyit', 'fkit', 3.33)
# 计算元组相加
sum_tuple = a_tuple + b_tuple
print(sum_tuple) # ('crazyit', 20, -1.2, 127, 'crazyit', 'fkit', 3.33)
print(a_tuple) # a_tuple并没有改变
print(b_tuple) # b_tuple并没有改变
# 两个元组相加
print(a_tuple + (-20 , -30)) # ('crazyit', 20, -1.2, -20, -30)
# 下面代码报错:元组和列表不能直接相加
#print(a_tuple + [-20 , -30])
a_list = [20, 30, 50, 100]
b_list = ['a', 'b', 'c']
# 计算列表相加
sum_list = a_list + b_list
print(sum_list) # [20, 30, 50, 100, 'a', 'b', 'c']
print(a_list + ['fkit']) # [20, 30, 50, 100, 'fkit']
输出结果:
('crazyit', 20, -1.2, 127, 'crazyit', 'fkit', 3.33)
('crazyit', 20, -1.2)
(127, 'crazyit', 'fkit', 3.33)
('crazyit', 20, -1.2, -20, -30)
[20, 30, 50, 100, 'a', 'b', 'c']
[20, 30, 50, 100, 'fkit']
乘法
列表和元组可以和整数执行乘法运算,列表和元组乘法的意义就是把它们包含的元素重复N次 ---- N就是被乘的倍数。
示例:
# 同时对元组使用加法、乘法
order_endings = ('st', 'nd', 'rd')
+ ('th',) * 17 + ('st', 'nd', 'rd')
+ ('th',) * 7 + ('st',)
# 将会看到st、nd、rd、17个th、st、nd、rd、7个th、st
print(order_endings)
day = input("输入日期(1-31):")
# 将字符串转成整数
day_int = int(day)
print(day + order_endings[day_int - 1])
输出结果:
('st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'st')
输入日期(1-31):27
27th
注意:('th')和'th'是相同的,为了表示只有一个元素的元组,必须在唯一的元组元素之后添加英文逗号。
in运算符
in运算符用于判断列表或元组是否包含某个元素
示例:
a_tuple = ('crazyit' , 20, -1.2)
print(20 in a_tuple) # True
print(1.2 in a_tuple) # False
print('fkit' not in a_tuple) # True
长度、最大值和最小值
Python提供了内置的len()、min()、max()全局函数获取元组或列表的长度、最大值和最小值
由于min()、max()要对元组、列表中的元素比较大小,因此程序要求传给min()、max()函数的元组、列表的元素必须是相同类型且可以比较大小
# 元素都是数值的元组
a_tuple = (20, 10, -2, 15.2, 102, 50)
# 计算最大值
print(max(a_tuple)) # 102
# 计算最小值
print(min(a_tuple)) # -2
# 计算长度
print(len(a_tuple)) # 6
# 元素都是字符串的列表
b_list = ['crazyit', 'fkit', 'Python', 'Kotlin']
# 计算最大值(依次比较每个字符的ASCII码值,先比较第一个字符,若相同,继续比较第二个字符,以此类推)
print(max(b_list)) # fkit(26个小写字母的ASCII码为97~122)
# 计算最小值
print(min(b_list)) # Kotlin (26个大写字母的ASCII码为65~90)
# 计算长度
print(len(b_list)) # 4
序列封包和序列解包
简单说,python支持以下两种赋值方式:
- 程序把多个值赋给一个变量时,Python会自动将多个值封装成元组。这种功能被称为序列封包。
- 程序允许将序列(列表或元组等)直接赋值给多个变量,此时序列的各元素会被依次赋值给每个变量(要求序列的元素个数和变量个数相等)。这种功能被称为序列解包。
实例:
# 序列封包:将10、20、30封装成元组后赋值给vals
vals = 10, 20, 30
print(vals) # (10, 20, 30)
print(type(vals)) # <class 'tuple'>
print(vals[1]) # 20
a_tuple = tuple(range(1, 10, 2))
# print(a_tuple) # (1, 3, 5, 7, 9)
# 序列解包: 将a_tuple元组的各元素依次赋值给a、b、c、d、e变量
a, b, c, d, e = a_tuple
print(a, b, c, d, e) # 1 3 5 7 9
a_list = ['fkit', 'crazyit']
# 序列解包: 将a_list序列的各元素依次赋值给a_str、b_str变量
a_str, b_str = a_list
print(a_str, b_str) # fkit crazyit
输出结果:
(10, 20, 30)
<class 'tuple'>
20
1 3 5 7 9
fkit crazyit
如果在赋值中同时运用了序列封包和序列解包机制,就可以让赋值运算符支持同时将多个值赋给多个变量
# 将10、20、30依次赋值给x、y、z
x, y, z = 10, 20, 30
print(x, y, z) # 10 20 30
上述代码实际上相当于如下执行过程:
// 先执行序列封包
xyz=10,20,30
// 再执行序列解包
x,y,z=10,20,30
使用这种语法也可以实现交换变量的值:
# 将y,z, x依次赋值给x、y、z
x, y, z = y, z, x
print(x, y, z) # 20 30 10
在序列解包时也可以只解出部分变量,剩下的依然使用列表变量保存。为了使用这种解包方式,Python允许在左边被赋值的变量之前添加“*”,那么该变量就代表一个列表,可以保存多个集合元素。
# first、second保存前2个元素,rest列表包含剩下的元素
first, second, *rest = range(10)
print(first) # 0
print(second) # 1
print(rest) # [2, 3, 4, 5, 6, 7, 8, 9]
# last保存最后一个元素,begin保存前面剩下的元素
*begin, last = range(10)
print(begin) # [0, 1, 2, 3, 4, 5, 6, 7, 8]
print(last) # 9
# first保存第一个元素,last保存最后一个元素,middle保存中间剩下的元素
first, *middle, last = range(10)
print(first) # 0
print(middle) # [0, 1, 2, 3, 4, 5, 6, 7, 8]
print(last) # 9
输出结果:
0
1
[2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
9
0
[1, 2, 3, 4, 5, 6, 7, 8]
9
使用列表
创建列表
除了使用方括号语法创建列表之外,Python还提供了一个内置的list()函数来创建列表,list()函数可用于将元组、区间(range)等对象转换为列表。
a_tuple = ('crazyit', 20, -1.2)
# 将元组转换成列表
a_list = list(a_tuple)
print(a_list)
# 使用range()函数创建区间(range)对象
a_range = range(1, 5)
print(a_range) # range(1, 5)
# 将区间转换成列表
b_list = list(a_range)
print(b_list) #[1, 2, 3, 4]
# 创建区间时还指定步长
c_list = list(range(4, 20, 3))
print(c_list) # [4, 7, 10, 13, 16, 19]
输出结果:
['crazyit', 20, -1.2]
range(1, 5)
[1, 2, 3, 4]
[4, 7, 10, 13, 16, 19]
与list()对应的是,Python也提供了一个tuple()函数,该函数可用于将列表、区间(range)等对象转换为元组。
a_list = ['crazyit', 20, -1.2]
# 将列表转换成元组
a_tuple = tuple(a_list) # ('crazyit', 20, -1.2)
print(a_tuple)
# 使用range()函数创建区间(range)对象
a_range = range(1, 5)
print(a_range) # range(1, 5)
# 将区间转换成元组
b_tuple = tuple(a_range)
print(b_tuple) #(1, 2, 3, 4)
# 创建区间时还指定步长
c_tuple = tuple(range(4, 20, 3))
print(c_tuple) #(4, 7, 10, 13, 16, 19)
输出结果:
('crazyit', 20, -1.2)
range(1, 5)
(1, 2, 3, 4)
(4, 7, 10, 13, 16, 19)
增加列表元素
使用列表的append()方法,该方法会把传入的参数追加到列表的最后面。append()方法即可接受单个值,也可接受元组、列表等,但该方法只是把元素、列表当成单个元素,这样就会形成在列表中嵌套列表、嵌套元组的情形。
a_list = ['crazyit', 20, -2]
# 追加元素
a_list.append('fkit')
print(a_list) # ['crazyit', 20, -2, 'fkit']
a_tuple = (3.4, 5.6)
# 追加元组,元组被当成一个元素
a_list.append(a_tuple)
print(a_list) # ['crazyit', 20, -2, 'fkit', (3.4, 5.6)]
# 追加列表,列表被当成一个元素
a_list.append(['a', 'b'])
print(a_list) # ['crazyit', 20, -2, 'fkit', (3.4, 5.6), ['a', 'b']]
输出结果:
['crazyit', 20, -2, 'fkit']
['crazyit', 20, -2, 'fkit', (3.4, 5.6)]
['crazyit', 20, -2, 'fkit', (3.4, 5.6), ['a', 'b']]
从代码中可以看出,为列表追加另一个列表时,Python会将被追加的列表当成一个整体的元素,而不是追加目标列表中的元素。如果希望不将被追加的列表当成一个整体,而只是追加列表中的元素,则可使用列表的extend()方法。
b_list = ['a', 30]
# 追加元组中的所有元素
b_list.extend((-2, 3.1))
print(b_list) # ['a', 30, -2, 3.1]
# 追加列表中的所有元素
b_list.extend(['C', 'R', 'A'])
print(b_list) # ['a', 30, -2, 3.1, 'C', 'R', 'A']
# 追加区间中的所有元素
b_list.extend(range(97, 100))
print(b_list) # ['a', 30, -2, 3.1, 'C', 'R', 'A', 97, 98, 99]
输出结果:
['a', 30, -2, 3.1]
['a', 30, -2, 3.1, 'C', 'R', 'A']
['a', 30, -2, 3.1, 'C', 'R', 'A', 97, 98, 99]
如果希望在列表中间增加元素,则可使用列表的insert()方法,使用insert()方法时要指定将元素插入列表的哪个位置。
c_list = list(range(1, 6))
print(c_list) # [1, 2, 3, 4, 5]
# 在索引3处插入字符串
c_list.insert(3, 'CRAZY' )
print(c_list) # [1, 2, 3, 'CRAZY', 4, 5]
# 在索引3处插入元组,元组被当成一个元素
c_list.insert(3, tuple('crazy'))
print(c_list) # [1, 2, 3, ('c', 'r', 'a', 'z', 'y'), 'CRAZY', 4, 5]
输出结果:
[1, 2, 3, 4, 5]
[1, 2, 3, 'CRAZY', 4, 5]
[1, 2, 3, ('c', 'r', 'a', 'z', 'y'), 'CRAZY', 4, 5]
删除列表元素
删除列表元素使用del语句。del语句是python的一种语句,专门用于执行删除操作,不仅可以用于删除列表元素,也可用于删除变量等。
使用del语句即可删除列表中的单个元素,也可直接删除列表中的中间一段。
a_list = ['crazyit', 20, -2.4, (3, 4), 'fkit']
# 删除第3个元素
del a_list[2]
print(a_list) # ['crazyit', 20, (3, 4), 'fkit']
# 删除第2个到第4个(不包含)元素
del a_list[1: 3]
print(a_list) # ['crazyit', 'fkit']
b_list = list(range(1, 10))
# 删除第3个到倒数第2个(不包含)元素,间隔为2
del b_list[2: -2: 2]
print(b_list) # [1, 2, 4, 6, 8, 9]
# 删除第3个到第5个(不包含)元素
del b_list[2: 4]
print(b_list) # [1, 2, 8, 9]
输出结果:
['crazyit', 20, (3, 4), 'fkit']
['crazyit', 'fkit']
[1, 2, 4, 6, 8, 9]
[1, 2, 8, 9]
使用del语句不仅可以删除列表元素,也可以删除普通变量
name = 'crazyit'
print(name) # crazyit
# 删除name变量
del name
print(name) # NameError
输出结果:
crazyit
Traceback (most recent call last):
File "C:Userszz.spyder-py3 emp.py", line 6, in <module>
print(name) # NameError
NameError: name 'name' is not defined
除使用del语句之外,Python还提供了remove()方法来删除列表元素,该方法并不是根据索引来删除元素的,而是根据元素本身来执行删除操作的。该方法只删除第一个找到的元素,如果找不到该元素,该方法将会引发ValueError错误。
c_list = [20, 'crazyit', 30, -4, 'crazyit', 3.4]
# 删除第一次找到的30
c_list.remove(30)
print(c_list) # [20, 'crazyit', -4, 'crazyit', 3.4]
# 删除第一次找到的'crazyit'
c_list.remove('crazyit')
print(c_list) # [20, -4, 'crazyit', 3.4]
输出结果:
[20, 'crazyit', -4, 'crazyit', 3.4]
[20, -4, 'crazyit', 3.4]
列表还包含一个clear()方法,该方法用于清空列表的所有元素,示例:
c_list = [20, 'crazyit', 30, -4, 'crazyit', 3.4]
print(c_list)
c_list.clear()
print(c_list) # []
输出结果:
[20, 'crazyit', 30, -4, 'crazyit', 3.4]
[]
修改列表元素
列表的元素相当于变量,因此程序可以对列表的元素赋值,这样既可修改列表的元素
a_list = [2, 4, -3.4, 'crazyit', 23]
# 对第3个元素赋值
a_list[2] = 'fkit'
print(a_list) # [2, 4, 'fkit', 'crazyit', 23]
# 对倒数第2个元素赋值
a_list[-2] = 9527
print(a_list) # [2, 4, 'fkit', 9527, 23]
输出结果:
[2, 4, 'fkit', 'crazyit', 23]
[2, 4, 'fkit', 9527, 23]
此外,程序也可通过slice语法对列表其中一部分赋值,在执行这个操作时并不要求新赋值的元素个数与原来的元素个数相等。这意味着通过这种方式即可为列表增加元素,也可为列表删除元素
b_list = list(range(1, 5))
print(b_list)
# 将第2个到第4个(不包含)元素赋值为新列表的元素
b_list[1: 3] = ['a', 'b']
print(b_list) # [1, 'a', 'b', 4]
输出结果:
[1, 2, 3, 4]
[1, 'a', 'b', 4]
如果对列表中空的slice赋值,就变成了为列表插入元素
b_list = list(range(1, 5))
# 将第3个到第3个(不包含)元素赋值为新列表的元素,就是插入
b_list[2: 2] = ['x', 'y']
print(b_list) # [1, 'a', 'x', 'y', 'b', 4]
输出结果:
[1, 2, 'x', 'y', 3, 4]
如果将列表其中一段赋值为空列表,就变成了从列表中删除元素
b_list = list(range(1, 7))
print(b_list)
# 将第3个到第6个(不包含)元素赋值为空列表,就是删除
b_list[2: 5] = []
print(b_list)
输出结果:
[1, 2, 3, 4, 5, 6]
[1, 2, 6]
对列表使用slice语法赋值时,不能使用单个值;如果使用字符串赋值,Python会自动把字符串当成序列处理,其中每个字符都是一个元素
b_list = list(range(1, 7))
print(b_list)
# Python会自动将str分解成序列
b_list[1: 3] = 'Charlie'
print(b_list) # [1, 'C', 'h', 'a', 'r', 'l', 'i', 'e']
输出结果:
[1, 2, 3, 4, 5, 6]
[1, 'C', 'h', 'a', 'r', 'l', 'i', 'e', 4, 5, 6]
在使用slice语法赋值时,也可指定step参数。但如果指定了step参数,则要求所赋值的列表元素个数与所替换的列表元素个数相等
c_list = list(range(1, 10))
# 指定step为2,被赋值的元素有4个,因此用于赋值的列表也必须有4个元素
c_list[2: 9: 2] = ['a', 'b', 'c', 'd']
print(c_list) # [1, 2, 'a', 4, 'b', 6, 'c', 8, 'd']
输出结果:
[1, 2, 'a', 4, 'b', 6, 'c', 8, 'd']
列表的其他常用方法
在交互式解释器中使用dir(list)即可看到列表包含的所有方法,示例:
dir(list)
['__add__',
'__class__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__iadd__',
'__imul__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__reversed__',
'__rmul__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'append',
'clear',
'copy',
'count',
'extend',
'index',
'insert',
'pop',
'remove',
'reverse',
'sort']
- count():用于统计列表中某个元素出现的次数
- index():用于判断某个元素在列表中出现的位置
- pop():用于将列表当成"栈"使用,实现元素出栈功能
- reverse():用于将列表中的元素反向存放
- sort():用于对列表元素排序
a_list = [2, 30, 'a', [5, 30], 30]
# 计算列表中30的出现次数
print(a_list.count(30)) # 2
# 计算列表中[5, 30]的出现次数
print(a_list.count([5, 30])) # 1
index()方法用于定位某个元素在列表中出现的位置,如果该元素没有出现,则会引发ValueError错误。在使用index()方法时还可传入start、end参数,用于在列表的指定范围内搜索元素。
a_list = [2, 30, 'a', 'b', 'crazyit', 30]
# 定位元素30的出现位置
print(a_list.index(30)) # 1
# 从索引2处开始、定位元素30的出现位置
print(a_list.index(30, 2)) # 5
# 从索引2处到索引4处之间定位元素30的出现位置,找不到该元素
print(a_list.index(30, 2, 4)) # ValueError
输出结果:
2
1
pop()方法用于实现元素出栈功能。栈是一种特殊的数据结构,它可实现先入后出功能,即先加入栈的元素,反而后出栈。
stack = []
# 向栈中“入栈”3个元素
stack.append("fkit")
stack.append("crazyit")
stack.append("Charlie")
print(stack) # ['fkit', 'crazyit', 'Charlie']
# 第一次出栈:最后入栈的元素被移出栈
print(stack.pop())
print(stack) # ['fkit', 'crazyit']
# 再次出栈
print(stack.pop())
print(stack) # ['fkit']
输出结果:
['fkit', 'crazyit', 'Charlie']
Charlie
['fkit', 'crazyit']
crazyit
['fkit']
该操作将会把最后一次添加的元素移出栈,且该方法会返回出栈的元素。
reverse()方法会将列表中所有元素的顺序反转,示例:
a_list = list(range(1, 8))
# 将a_list列表元素反转
a_list.reverse()
print(a_list) # [7, 6, 5, 4, 3, 2, 1]
sort()方法用于对列表元素进行排序,示例:
a_list = [3, 4, -2, -30, 14, 9.3, 3.4]
# 对列表元素排序
a_list.sort()
print(a_list) #[-30, -2, 3, 3.4, 4, 9.3, 14]
b_list = ['Python', 'Swift', 'Ruby', 'Go', 'Kotlin', 'Erlang']
# 对列表元素排序:默认按字符串包含的字符的编码大小比较
b_list.sort()
print(b_list) # ['Erlang', 'Go', 'Kotlin', 'Python', 'Ruby', 'Swift']
输出结果:
[-30, -2, 3, 3.4, 4, 9.3, 14]
['Erlang', 'Go', 'Kotlin', 'Python', 'Ruby', 'Swift']
sort()方法还可传入key和reverse两个参数,而且这两个参数必须通过参数名指定(这种参数叫做关键字参数)。key参与用于为每个元素都生成一个比较大小的“键”;reverse参数则用于执行是否需要反转排序 --- 默认是从小到大排序;如果将该参数设置为True,将会改为从大到小排序。
b_list = ['Python', 'Swift', 'Ruby', 'Go', 'Kotlin', 'Erlang']
# 指定key为len,指定使用len函数对集合元素生成比较的键,
# 也就是按字符串的长度比较大小
b_list.sort(key=len)
print(b_list) # ['Go', 'Ruby', 'Swift', 'Erlang', 'Kotlin', 'Python']
# 指定反向排序
b_list.sort(key=len, reverse=True)
print(b_list) # ['Erlang', 'Kotlin', 'Python', 'Swift', 'Ruby', 'Go']
输出结果:
['Go', 'Ruby', 'Swift', 'Python', 'Kotlin', 'Erlang']
['Python', 'Kotlin', 'Erlang', 'Swift', 'Ruby', 'Go']
使用字典
用于存放具有映射关系的数据。
字典入门
字典相当于保存了两组数据,其中一组数据是关键数组,被称为Key;另一组数据可通过key来访问,被称为value。字典中的key是非常关键的数组,不允许重复。
创建字典
程序即可使用花括号语法来创建字典,也可使用dict()函数来创建字典。实际上,dict是一种类型,它就是python中的字典类型。
在使用花括号语法创建字典时,花括号中应包含多个key-value对,key与value之间用英文冒号隔开;多个key-value对之间用英文逗号隔开。
scores = {'语文': 89, '数学': 92, '英语': 93}
print(scores)
# 空的花括号代表空的dict
empty_dict = {}
print(empty_dict)
# 使用元组作为dict的key
dict2 = {(20, 30):'good', 30:'bad'}
print(dict2)
在使用dict()函数创建字典时,可以传入多个列表或元组参数作为key-value对,每个列表或元组将被当成一个key-value对,因此这些列表或元组都只能包含两个元素。
vegetables = [('celery', 1.58), ('brocoli', 1.29), ('lettuce', 2.19)]
# 创建包含3组key-value对的字典
dict3 = dict(vegetables)
print(dict3) # {'celery': 1.58, 'brocoli': 1.29, 'lettuce': 2.19}
cars = [['BMW', 8.5], ['BENS', 8.3], ['AUDI', 7.9]]
# 创建包含3组key-value对的字典
dict4 = dict(cars)
print(dict4) # {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
输出结果:
{'celery': 1.58, 'brocoli': 1.29, 'lettuce': 2.19}
{'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
如果不为dict()传入任何参数,则代表创建一个空的字典
# 创建空的字典
dict5 = dict()
print(dict5) # {}
还可通过为dict指定关键字参数创建字典,此时字典的key不允许使用表达式
# 使用关键字参数来创建字典
dict6 = dict(spinach = 1.39, cabbage = 2.59)
print(dict6) # {'spinach': 1.39, 'cabbage': 2.59}
其key直接写spinach、cabbage,不能将它们放在引号中(注:放在引号中会报错:SyntaxError: keyword can't be an expression)。
字典的基本用法
对于初学者而言,应牢记字典包含多个key-value对,而key是字典的关键数据,因此程序对字典的操作都是基于key的。
通过key访问value使用的也是方括号语法,方括号中放的是key,而不是列表或元组中的索引。
scores = {'语文': 89}
# 通过key访问value
print(scores['语文'])
输出结果:
89
如果要为dict添加key-value对,只需为不存在的key赋值即可。
scores = {'语文': 89}
# 对不存在的key赋值,就是增加key-value对
scores['数学'] = 93
scores[92] = 5.7
print(scores) # {'语文': 89, '数学': 93, 92: 5.7}
输出结果:
{'语文': 89, '数学': 93, 92: 5.7}
如果要删除列表中key-value对,则可使用del语句。
del scores['语文']
del scores['数学']
print(scores) # {92: 5.7}
输出结果:
{92: 5.7}
如果对dict中存在的key-value对赋值,新赋的value就会覆盖原有的value,这样即可改变dict中的key-value对。
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
# 对存在的key-value对赋值,改变key-value对
cars['BENS'] = 4.3
cars['AUDI'] = 3.8
print(cars) # {'BMW': 8.5, 'BENS': 4.3, 'AUDI': 3.8}
输出结果:
{'BMW': 8.5, 'BENS': 4.3, 'AUDI': 3.8}
如果要判断是否包含指定的key,则可以使用in 或 not in 运算符。需要指出的是,对于dict而言,in或not in运算符都是基于key来判断的。
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
# 判断cars是否包含名为'AUDI'的key
print('AUDI' in cars) # True
# 判断cars是否包含名为'PORSCHE'的key
print('PORSCHE' in cars) # False
print('LAMBORGHINI' not in cars) # True
输出结果:
True
False
True
通过上面可以看到,字典的key是它的关键。换个角度看,字典的key就相当于它的索引,字典的key可以是任意不可变类型。
字典的常用方法
字典由dict类代表,可使用dir(dict)来查看该类包含哪些方法,示例:
dir(dict)
['__class__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'clear',
'copy',
'fromkeys',
'get',
'items',
'keys',
'pop',
'popitem',
'setdefault',
'update',
'values']
clear()用于清空字典中所有的key-value对,执行该方法后,该字典就变成了空字典
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
print(cars) # {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
# 清空cars所有key-value对
cars.clear()
print(cars) # {}
输出结果:
{'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
{}
get()方法其实就是根据key来获取value,它相当于方括号语法的增强版 --- 当使用方括号访问不存在的key时,字典会引发KeyError错误;如果使用get()方法访问不存在的key,该方法会简单的返回None,不会导致错误。
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
# 获取'BMW'对应的value
print(cars.get('BMW')) # 8.5
print(cars.get('PORSCHE')) # None
print(cars['PORSCHE']) # KeyError
输出结果:
8.5
None
Traceback (most recent call last):
File "C:Userszz.spyder-py3 emp.py", line 6, in <module>
print(cars['PORSCHE']) # KeyError
KeyError: 'PORSCHE'
update()方法可使用一个字典所包含的key-value对来更新已有的字典。在执行update()方法时,如果被更新的字典中已包含对应的key-value对,那么原value会被覆盖;如果被更新的字典中不包含对应的key-value对,则该key-value对被添加进去。示例:
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
cars.update({'BMW':4.5, 'PORSCHE': 9.3})
print(cars)
输出结果:
{'BMW': 4.5, 'BENS': 8.3, 'AUDI': 7.9, 'PORSCHE': 9.3}
item()、keys()、values() 分别用于获取字典中的所有key-value对、所有key、所有value。这三个方法依次返回dict_items、dict_keys、dict_values对象。python不希望用户直接操作者三个方法,但可通过list()函数把它们转换成列表。示例:
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
# 获取字典所有的key-value对,返回一个dict_items对象
ims = cars.items()
print(type(ims)) # <class 'dict_items'>
# 将dict_items转换成列表
print(list(ims)) # [('BMW', 8.5), ('BENS', 8.3), ('AUDI', 7.9)]
# 访问第2个key-value对
print(list(ims)[1]) # ('BENS', 8.3)
# 获取字典所有的key,返回一个dict_keys对象
kys = cars.keys()
print(type(kys)) # <class 'dict_keys'>
# 将dict_keys转换成列表
print(list(kys)) # ['BMW', 'BENS', 'AUDI']
# 访问第2个key
print(list(kys)[1]) # 'BENS'
# 获取字典所有的value,返回一个dict_values对象
vals = cars.values()
# 将dict_values转换成列表
print(type(vals)) # [8.5, 8.3, 7.9]
# 访问第2个value
print(list(vals)[1]) # 8.3
输出结果:
<class 'dict_items'>
[('BMW', 8.5), ('BENS', 8.3), ('AUDI', 7.9)]
('BENS', 8.3)
<class 'dict_keys'>
['BMW', 'BENS', 'AUDI']
BENS
<class 'dict_values'>
8.3
pop方法用于获取指定key对应的value,并删除这个key-value对,示例:
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
print(cars.pop('AUDI')) # 7.9
print(cars) # {'BMW': 8.5, 'BENS': 8.3}
popitem()方法用于随机弹出字典中的一个key-value对
cars = {'AUDI': 7.9, 'BENS': 8.3, 'BMW': 8.5}
print(cars)
# 弹出字典底层存储的最后一个key-value对
print(cars.popitem()) # ('AUDI', 7.9)
print(cars) # {'BMW': 8.5, 'BENS': 8.3}
# 将弹出项的key赋值给k、value赋值给v
k, v = cars.popitem()
print(k, v) # BENS 8.3
输出结果:连续运行2次
runfile('C:/Users/zh/.spyder-py3/temp.py', wdir='C:/Users/zh/.spyder-py3')
{'AUDI': 7.9, 'BENS': 8.3, 'BMW': 8.5}
('BMW', 8.5)
{'AUDI': 7.9, 'BENS': 8.3}
BENS 8.3
runfile('C:/Users/zh/.spyder-py3/temp.py', wdir='C:/Users/zh/.spyder-py3')
{'AUDI': 7.9, 'BENS': 8.3, 'BMW': 8.5}
('BMW', 8.5)
{'AUDI': 7.9, 'BENS': 8.3}
BENS 8.3
setdefault()方法也用于根据key来获取对应value的值。但该方法有一个额外的功能 --- 当程序要获取的key在字典中不存在时,该方法会为这个不存在的key设置一个默认的value,然后再返回该key对应的value。如果该key-value对存在,则直接返回该key对应的value
cars = {'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9}
# 设置默认值,该key在dict中不存在,新增key-value对
print(cars.setdefault('PORSCHE', 9.2)) # 9.2
print(cars)
# 设置默认值,该key在dict中存在,不会修改dict内容
print(cars.setdefault('BMW', 3.4)) # 8.5
print(cars)
输出结果:
9.2
{'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9, 'PORSCHE': 9.2}
8.5
{'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9, 'PORSCHE': 9.2}
fromkeys()方法用于给指定的多个key创建字典,这些key对应的value默认都是None,也可以额外传入一个参数作为默认的value。该方法通常直接通过dict类调用,示例:
# 使用列表创建包含2个key的字典
a_dict = dict.fromkeys(['a', 'b'])
print(a_dict) # {'a': None, 'b': None}
# 使用元组创建包含2个key的字典
b_dict = dict.fromkeys((13, 17))
print(b_dict) # {13: None, 17: None}
# 使用元组创建包含2个key的字典,指定默认的value
c_dict = dict.fromkeys((13, 17), 'good')
print(c_dict) # {13: 'good', 17: 'good'}
输出结果:
{'a': None, 'b': None}
{13: None, 17: None}
{13: 'good', 17: 'good'}
使用字典格式化字符串
前面介绍过在格式化字串时,如果要格式化的字串模板中包含多个变量,后面就需要按顺序给出多个变量,这种方式对于字符串模板中包含少量变量的情况下是合适的,但如果字符串中包含大量的变量,这种按顺序提供变量的方式则有些不合适,可改为在字符串模板中按key指定变量,然后通过字典为字符串模板中的key设置值。
# 字符串模板中使用key
temp = '书名是:%(name)s, 价格是:%(price)010.2f, 出版社是:%(publish)s'
book = {'name':'疯狂Python讲义', 'price': 88.9, 'publish': '电子社'}
# 使用字典为字符串模板中的key传入值
print(temp % book)
book = {'name':'疯狂Kotlin讲义', 'price': 78.9, 'publish': '电子社'}
# 使用字典为字符串模板中的key传入值
print(temp % book)
# 前后变换顺序
book = {'publish': '电子社1','name':'疯狂Kotlin讲义1', 'price': 78.91}
# 使用字典为字符串模板中的key传入值
print(temp % book)
输出结果:
书名是:疯狂Python讲义, 价格是:0000088.90, 出版社是:电子社
书名是:疯狂Kotlin讲义, 价格是:0000078.90, 出版社是:电子社
书名是:疯狂Kotlin讲义1, 价格是:0000078.91, 出版社是:电子社1
本章小结
本章重点介绍了Python内置的三种重要的数据结构:列表、元组和字典,这三种数据结构是Python编程的重要基础。所有编程都离不开一些基础的数据结构,而列表、元组和字典就是这些基础数据结构的实现。其中列表和元组都代表元素有序、可通过索引访问元素的数据结构,区别只是列表是可变的 --- 程序可以添加、删除、替换列表元素:元组是不可变的 --- 程序不能改变元组中的元素。而字典则用于保存key-value对,这种类型在有些语言中也叫Map。其实无论学习哪种编程语言,列表、set、字典都是最基本的容器类型,而列表和字典尤其重要。
原文来源于我的语雀,我的微信公众号:细细研磨