Python:列表、元组和字典

3.1 序列简介

所谓序列,指的就是一种包含多项数据的数据结构,序列包含的多个数据项(也叫成员)按顺序排列,可通过索引来访问成员。

3.1.1 python的序列

python的常见序列类型包括字符串、列表 和元组等。

列表和元组两种类型看起来非常相似,最主要的区别在于:元组是不可变的,元组一旦构建出来,程序就不能修改元组所包含的成员(就像字符串也是不可变的,程序无法修改字符串所包含的字符序列);但序列是可变的,程序可以修改序列所包含的元素。

在具体的编程过程中,如果只是固定地保存多个数据项,则不需要修改它们,此时就应该使用元组;反之,就应该使用序列。此外,在某些时候,程序需要使用不可变的对象,比如Python要求字典的key必须是不可变的,此时程序只能使用元组。

提示:序列和元组的关系就是可变和不可变的关系。

3.1.2 创建列表和元组

创建列表和元组的语法也有点相似,区别只是创建列表使用方括号,创建元组使用圆括号,并在括号中列出元组的元素,元素之间以英文逗号隔开。

创建列表的语法格式如下:

[ele1,ele2,ele3,...]

创建元组的语法格式如下:

(ele1,ele2,ele3,...)

示例如下:

#使用方括号定义列表

my_list=['crazyit',20,'Python']

print(my_list)#['crazyit', 20, 'Python']

#使用圆括号定义元组

my_tuple=('crazy',20,'Python')

print(my_tuple)#('crazy', 20, 'Python')

3.2 列表和元组的通用用法

列表和元组非常相似,它们包含多个元素,多个元素也有各自的索引。程序可通过索引来操作这些元素,只要不涉及改变元素的操作,列表和元组的用法是通用的。

3.2.1 通过索引使用元素

列表和元组都可以通过索引来访问元素,它们的索引都是从0开始的,第一个元素的索引是0,第二个元素的索引是1……依次类推;它们也支持使用负数索引,倒数第一个元素的索引为-1,倒数第二个元素的索引为-2……依次类推。

列表的元素相当于一个变量,程序即可使用它的值,也可对元素赋值;元组的元素相当于一个常量,程序只能使用它的值,不能对其重新赋值。

a_tuple=('crazyit',20,5.6,'fkit',-17)

print(a_tuple)#('crazyit', 20, 5.6, 'fkit', -17)

#访问第一个元素

print(a_tuple[0])#crazyit

#访问第二个元素

print(a_tuple[1])#20

#访问倒数第一个元素

print(a_tuple[-1])#-17

#访问倒数第二个元素

print(a_tuple[-2])#fkit

3.2.2 子序列

与前面介绍的字符串操作类似,列表和元组同样可以使用索引获取中间一段,这种用法称为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)

#访问从倒数第三个到倒数第一个(不包含)的所有元素

print(a_tuple[-3:-1])#(5.6,'fkit')

#访问从第二个到倒数第二个(不包含)的所有元素

print(a_tuple[1:-2])#(20,-5.6)

#访问从倒数第三个到第五个(不包含)的所有元素

print(a_tuple[-1:4])#(5.6,'fkit')

如果指定step参数,则可间隔step个元素再取元素。

b_tuple=(1,2,3,4,5,6,7,8,9)

#访问从第三个到第九个(不包含)、间隔为2的所有元素

print(b_tuple[2:8:2])#(3,5,7)

#访问从第三个到第九个(不包含)、间隔为3的所有元素

print(b_tuple[2:8:3])#(3,6)

#访问从第三个到倒数第二个(不包含)、间隔为2的所有元素

print(b_tuple[2:-2:2])#(3,5,7)

3.2.3 加法

列表和元组支持加法运算,加法的和就是两个列表或元组所包含的元素的总和。

需要指出的是,列表只能和列表相加;元组只能和元组相加;元组不能直接和列表相加。

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没改变('crazyit', 20, -1.2)
print(b_tuple)#b_tuple没有改变(127, 'crazyit', 'fkit', 3.33)
#两个元组相加
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']

3.2.4 乘法

列表和元组可以和整数执行乘法运算,列表和元组乘法的意义就是把它们包含的元组的元素重复N次——N就是被乘的倍数。

a_tuple=('crazyit',20)
#执行乘法
mul_tuple=a_tuple*3
print(mul_tuple)#('crazyit', 20, 'crazyit', 20, 'crazyit', 20)
a_list=[30,'Python',2]
mul_list=a_list*3
print(mul_list)#[30, 'Python', 2, 30, 'Python', 2, 30, 'Python', 2]

当然,也可以对列表、元组同时进行加法、乘法运算。

#同时对元组使用加法和乘法
order_endings=('st','nd','rd')\
    +('th',)*17+('st','nd','rd') \
    +('th',)*17+('st',)
#将会看到st、nd、rd、17个th,st、nd、rd、7个th、st
print(order_endings)#('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', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'st')
day=input("输入日期(1-31):")
#将字符串转换为整数
day_int=int(day)
print(day+order_endings[day_int-1])
"""
输入日期(1-31):3
3rd
"""

上面同时对(’th’,)元组使用了乘法,再将乘法得到的结果使用加法连接起来,最后得到一个元组,该元组共有31个元素。

可能对(’th’,)这种写法感到好奇,此处明明只有一个元素,为何不用省略逗号?这是因为(’th’)只是字符串加上圆括号,并不是元组,也就是说,(’th’)和’th’相同。为了表示只有一个元素的元组,必须在唯一的元组元素之后添加英文逗号。

3.2.5 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

3.2.6 长度、最大值和最小值

python提供内置的len()、max()、min()全局函数来获取元组或列表的长度、最大值和最小值。

由于max()、min()必须队员组、列表中的元素比较大小,因此程序要求传给max()、min()函数的元组、列表的元素必须是相同类型且可以比较大小。

#元素都是数值的元组
a_tuple=(20,10,-2,15,2,102,50)
#计算最大值
print(max(a_tuple))#102
#计算最小值
print(min(a_tuple))#-2
#计算长度
print(len(a_tuple))#7
#元素都是字符串的列表
b_list=['crazyit','fkit','Python','Kotlin']
#计算最大值(依次比较每个字符的ACSII码值,先比较第一个字符与=,若相同,再比较第二个,以此类推)
print(max(b_list))#fkit
#计算最小值
print(min(b_list))#Kotlin
#计算长度
print(len(b_list))#4

上面首先使用三个函数对元素都是数值的元组进行处理,可以看到程序获取元组的最大值和最小值等。后半部分使用三个函数对元素都是字符串的列表进行处理,也可以看成程序获取列表的最大值、最小值等,这说明python的字符串也是可以比较大小的——Python依次按字符串中的每个字符对应得编码来比较字符串得大小。

3.2.7 序列封包和序列解包

Python还提供了序列封装包和序列解包的功能。简单来说,Python允许支持以下两种赋值方式。

(1)程序把多个值赋给一个变量时,python会自动将多个值封装成元组。这种功能被称为序列封装包。

(2)程序允许序列(元组或列表等)直接赋值给多个变量。此时序列的各元素会被依次赋值给每个变量(要求序列的元素个数和变量个数相等)。这种功能被称为序列解包。

#序列封包:将10、20、30封装成元组后赋值给vals
vals=10,20,30
print(vals)#(10, 20, 30)
print(type(vals))#
print(vals[1])#20
a_tuple=tuple(range(1,10,2))
#序列解包:将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依次赋值给x、y、z
x,y,z=10,20,30
print(x,y,z)#10 20 30

相当于:

#先执行序列封包
xyz=10,20,30
#再执行序列解包
x,y,z=xyz

使用这种语法也可以实现交换变量的值:

#先执行序列封包
xyz=10,20,30
#再执行序列解包
x,y,z=xyz
#将y、z、x依次赋值给x、y、z
x,y,z=y,z,x
print(x,y,z)#20 30 10

在序列解包时也可以只解出部分变量,剩下的依然使用列表变量保存。为了使用这种解包方式,Python允许在左边被赋值的变量之前添加“*”,那么该变量就代表一个列表,可以保存多个集合元素。

#first、second保存前两个元素,reat列表包含剩下的元素
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)#[1, 2, 3, 4, 5, 6, 7, 8]
print(last)#9

3.3 使用列表

前面说过,列表和元组最大的不同在于:元组的元素不可改变,列表的元素是可以改变的。元组支持的操作,列表基本上都支持;列表支持对元素进行修改,而元组不支持。从这个角度看,可以认为列表是增强版的元组。

注意:虽然大部分时候都可以使用列表来代替元组,但如果程序不需要修改列表所包含的元素,那么使用元组代替列表会更安全。

3.3.1 创建列表

除使用前面介绍的方括号语法创建列表之外,Python还提供了一个内置的list()函数来创建列表,list()函数可用于将元组、区间(range)等对象转换为列表。

a_tuple=('crazyit',20,-1.2)
#将元组转换成列表
a_list=list(a_tuple)
print(a_list)#['crazyit', 20, -1.2]
#使用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]

上面程序中使用list()将第一个元组转换成列表;使用list()将一个区间(range)对象转换成列表,转换的区间为range(1,5),该区间使用默认步长1,该区间包括1、2、3、4四个值(注意:不包含5)。因此程序输出b_list时才会看到四个数;使用list()将range(4,20,3)转换成列表,该区间为4到20(不包括20)且步长为3的数值。

与list()对应的时,Python也提供了一个tuple()函数,该函数可用于将列表、区间(range)等对象转换成元组。

a_list=['crazyit',20,-1.2]
#将列表转换成元组
a_tuple=tuple(a_list)
print(a_tuple)#('crazyit', 20, -1.2)
#使用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)

3.3.2 增加列表元素

为列表增加元素可调用列表的append()方法,该方法会把传入的参数追加到列表的最后面。

append()方法即可接收单个值,也可以接收元组、列表等,但该方法只是把元组、列表当成单个元素,这样就会形成在列表中嵌套列表、嵌套元组的情形。

a_list=['crazy',20,-2]
#追加元素
a_list.append('fkit')
print(a_list)#['crazy', 20, -2, 'fkit']
a_tuple=(3.4,5.6)
#追加元组,元组会被当成一个元素
a_list.append(a_tuple)
print(a_list)#['crazy', 20, -2, 'fkit', (3.4, 5.6)]
#追加列表,列表被当成一个元素
a_list.append(['a','b'])
print(a_list)#['crazy', 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]

此外,如果希望在列表的中间增加元素,则可以使用列表的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]

3.3.3 删除列表元素

删除列表元素使用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
del b_list[2:-2:2]
print(b_list)#[1, 2, 4, 6, 8, 9]
#删除第3个到第5个(不包含)元素,间隔为2
del b_list[2:5:2]
print(b_list)#[1, 2, 6, 9]

使用del语句不仅可以删除表元素,也可以删除普通变量。

name='crazyit'
print(name)#crazyit
#删除name变量
del name
print(name)#引发错误

除使用del语句之外,Python还提供了remove()方法来删除列表元素,该方法并不是根据索引来删除元素的,而是根据元素本身来执行删除操作的。该方法只删除第一个找到的元素,如果找不到该元素,该方法会引发错误。

c_list=[20,'crazyit',30,-4,'crazyit',3.4]
#删除第一次找到的20
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]

列表还包含一个clear()方法,正如它的名字所暗示的,该方法用于清空列表的所有元素。

c_list.clear()
print(c_list)#[]

3.3.4 修改列表元素

列表的元素相当于变量,因此程序可以对列表的元素进行赋值,这样即可修改列表元素。

a_list=[2,4,-3.4,'crazyit',23]
#对第三个元素进行赋值
a_list[2]='fkit'
print(a_list)#[2, 4, 'fkit', 'crazyit', 23]
#对倒数第二个元素进行赋值
a_list[-2]=9527
print(a_list)#[2, 4, 'fkit', 9527, 23]

上面代码通过索引对列表元素赋值,程序即可使用正数索引,也可使用负值索引,这都没有出错。

此外,程序也可以通过slice语法对列表其中一部分赋值,在执行这个操作时并不要求新赋值的元素个数与原来的元素个数相等。

这意味着通过这种方式既可为列表增加元素,也可为列表删除元素。

b_list=list(range(1,5))
print(b_list)#[1, 2, 3, 4]
#将第2个到第4个(不包含)元素赋值为新列表的元素
b_list[1:3]=['a','b']
print(b_list)#[1, 'a', 'b', 4]

如果对列表中空的slice赋值,就变成了为列表插入元素。

#如果对第三个到第三个(不包含)元素赋值为新列表的元素,就是插入元素
b_list[2:2]=['x','y']
print(b_list)#[1, 'a', 'x', 'y', 'b', 4]

如果对列表其中一段赋值为空列表,就变成了从列表中删除元素。

#将第三个到第六个(不包含)元素赋值为空列表,就是删除元素
b_list[2:5]=[]
print(b_list)#[1, 'a', 4]

对列表使用slice语法赋值时,不能使用单个值;如果使用字符串赋值,python会自动把字符串当成序列处理,其中每个字符就是一个元素。

#Python会自动将str分解成序列
b_list[1:3]='Charlie'
print(b_list)#[1, 'C', 'h', 'a', 'r', 'l', 'i', 'e']

在使用slice语法赋值时,也可指定step参数。但如果指定了step参数,则要求所赋值的列表元素个数与所替换的列表元素个数相等。

c_list=list(range(1,10))
#指定step为2,被复制的元素有4个,因此用于赋值的列表必须有四个元素
c_list[2:9:2]=['a','b','c','d']
print(c_list)#[1, 2, 'a', 4, 'b', 6, 'c', 8, 'd']

3.3.5 列表的其他常用方法

除上面介绍的增加元素,删除元素、修改元素方法之外,列表还包含了一些常用的方法。

在交互解释器中输入dir(list)即可看到列表包含的所有方法。

dir(list)
'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

备注:在上面输出结果中已经剔除了那些以双划线开头的方法。按照约定,这些方法都具有特殊的意义,不希望被用户直接调用。

上面有些方法已经介绍了,列表还包含如下常用方法可以使用:

  1. count():用于统计列表中某个元素出现的次数。
  2. index():用于判断某个元素在列表中出现的位置
  3. pop():用于将列表当成“栈”使用,实现元素出栈的功能。
  4. reverse():用于将列表中的元素反向存放。
  5. sort():用于对列表元素排序。
a_list=[2,30,'a',[5,20],30]
#计算列表中出现30的次数
print(a_list.count(30))#2
#计算列表中出现[5,20]的次数
print(a_list.count([5,20]))#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))#报错

pop(0方法用于实现元素出栈功能。栈是一种特殊的数据结构,它可实现先入后出(FILO)功能,即先加入栈,反而后出栈。

提示:在其他编程语言中所实现的“栈”中,往往会提供一个push()方法,用于实现入栈的操作,但Python的列表并没有提供push()方法,我们可以使用append()方法来替代push(0方法实现入栈操作。

stack=[]
#向栈中入栈3个元素
stack.append('fkit')
stack.append('crazyit')
stack.append('Charlie')
print(stack)#['fkit', 'crazyit', 'Charlie']
#第一次出栈:最后入栈的元素被移出栈
print(stack.pop())#Charlie
print(stack)#['fkit', 'crazyit']
#再次出栈
print(stack.pop())#crazyit
print(stack)#['fkit']

提示:与所有编程语言类似的是,出栈操作既会移除列表的最后一个元素,也会返回被移除的元素。

reverse()方法会将列表中所有元素的顺序反转。

a_list=list(range(1,8))
#将列表a_list反转
a_list.reverse()
print(a_list)#[7, 6, 5, 4, 3, 2, 1]

从上面程序可以看出,调用reverse()方法会反转列表中的所有元素。

sort()方法用于对列表元素进行排序。

a_list=[3,4,-2.-30,14,9.3,3.4]
#对元素进行排序
a_list.sort()
print(a_list)#[-32.0, 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']

sort()方法除支持默认排序之外,还可以传入key和reverse两个参数,而且这两个参数必须通过参数名指定(这种参数叫关键字参数)。key参数用于为每个元素都生成一个比较大小的“键”;reverse参数则用于是否需要反转排序——默认是从小到大排序;如果将参数设置为True,将会改为从大到小排序。

#指定key为len,指定使用len函数对集合元素生成比较大小的键
#也就是按字符的长度比较大小
b_list.sort(key=len)
print(b_list)#['Go', 'Ruby', 'Swift', 'Erlang', 'Kotlin', 'Python']
#指定反向排序
b_list.sort(reverse=True)
print(b_list)#['Swift', 'Ruby', 'Python', 'Kotlin', 'Go', 'Erlang']

上面两次排序时都将key参数指定为len,这意味着程序将会使用len()函数对集合元素生成比较大小的键,即根据元素的字符串长度比较大小。

3.4 使用字典

字典也是Python提供的一种常用的数据结构,它用于存放具有映射关系的数据。

3.4.1 字典入门

比如有成绩表数据——语文:79,数学:80,英语:92,这组数据看上去像两个列表,但这两个列表的元素之间有一定的关联关系。如果单纯使用两个列表来存放这组数据,则无法记录两组数据之间的关联关系。

为了保存具有映射关系的数据:Python提供了字典,字典相当于保存了两组数据,其中一组数据是关键数据,被称为key;另一组数据可提供key来访问,被称为value。

由于字典中的key是非常关键的数据,而且程序需要通过key来访问value,因此字典中的key不允许重复。

3.4.2 创建字典

程序即可使用花括号语法创建字典,也可使用dict()函数来创建字典。实际上,dict是一种类型,它是Python中的字典类型。

在使用花括号语法创建字典时,花括号中应该包括多个key-value对,key和value 之间用英文冒号隔开;多个key-value之间用英文逗号隔开。

scores={'语文':79,'数学':80,'英语':92}
print(scores)#{'语文': 79, '数学': 80, '英语': 92}
#空的花括号代表空的dict
empty_dict={}
print(empty_dict)#{}
#使用元组作为dict的key
dict2={(20,30):'good',30:'bad'}
print(dict2)#{(20, 30): 'good', 30: 'bad'}

需要指出的是,元组可以作为dict的key,但列表不能作为dict的key。这是由于dict要求key必须是不可变类型,但列表是可变类型,因此列表不能作为dict的key。

在使用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}

如果不为dict()函数传入任何参数,则代表创建一个空的字典。

#创建空的字典
dict5=dict()
print(dict5)#{}

还可以通过为dict指定关键字参数创建字典,比如字典的key不允许使用表达式。

#使用关键字参数来创建字典
dict6=dict(spinach=1.39,cabbage=2.59)
print(dict6)#{'spinach': 1.39, 'cabbage': 2.59}

3.4.3 字典的基本用法

刚学习的人,应该牢记多个key-value对,而key是字典的关键数据,因此程序对字典的操作都是基于key的。

  1. 通过key访问valu。
  2. 通过key添加key-value对
  3. 通过key删除key-value对
  4. 通过key修改key-value对
  5. 通过key判断指定key-value对是否存在

通过key访问value使用的也是方括号语法,就像前面介绍的列表和元组一样,只是此时在方括号放的是key,而不是列表或元组中的索引

scores={'语文':89}
#通过key访问value
print(scores['语文'])#89

如果要为dict添加key-value对,只需为不存在key赋值即可。

#对不存在的key赋值,就是添加key-value对
scores['数学']=93
scores[92]=57
print(scores)#{'语文': 89, '数学': 93, 92: 57}

如果要删除字典中的key-value对,则可使用del语句。

#使用del语句删除key-value对
del scores['语文']
del scores['数学']
print(scores)#{92: 57}

如果要判断字典是否包含指定的key,则可以使用in或not in运算符。需要指出的是,对于dict而言,in或not in运算符都是基于key来判断的。

#判断cars是否包含名为AUDI的key
print('AUDI' in cars)#True
#判断cars是否包含模拟华为哦PORSCHE的key
print('PORSCHE' in cars)#FALSE
print('LAMBOGHINT' not in cars)#True

通过上面介绍可以看出,字典的key是它的关键。换个角度来看,字典的key就相当于它的索引,只不过这些索引不一定是整数类型,字典的key可以是任意不可变的类型。

可以这样说,字典相当于索引是任意不可变类型的列表;而列表则相当于key只能是整数的字典。因此,如果程序中要使用的字典的key都是整数类型,则可考虑能否换成列表。

此外,还有一点需要之处,列表的索引总是从0开始、连续增大的;但字典的索引即使是整数类型,也不需要从0开始,而且不需要连续。因此,列表不允许对不存在的索引进行赋值;但字典允许直接对不存在的key赋值——这样就会为字典增加一个key-value对。

注意:列表不允许对不存在的索引赋值;但字典允许直接对不存在的key赋值。

3.4.4 字典的常用用法

字典由dict类代表,因此我们同样可使用dir(dict)来查看该类包含那些方法。在交互式解释器中输入dir(dict)命令。

dir(dict)
['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

下面介绍dict的一些方法。

clear()用于清空字典中的所有key-value对,对一个字典执行clear()方法之后,该字典就会变成一个空字典。

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)#{}

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'])#引发错误

update()方法可使用一个字典所包含地key-value对来更新已有的字典。在执行update()方法时,如果更新的字典中已包含对应的key-value对,那么原value会被覆盖;如果被更新的字典中不包含对应的key-value对,则该key-value对被添加进去。

cars={'BMW':8.5,'BENS':8.3,'AUDI':7.9}
#获取BMW对应的value
cars.update({'BMW':4.5,'PORSCHE':9.3})
print(cars)#{'BMW': 4.5, 'BENS': 8.3, 'AUDI': 7.9, 'PORSCHE': 9.3}

从上面的执行可以看出,由于被更新的dict中已包含key为“AUDI”的key-value对,因此更新时该key-value对的value将被改写;但如果被更新的dict中不包含key为“PORSCHE”的key-value对,那么更新时就会为原字典增加一个key-value对。

items()、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))#
#将dict_items转换成列表
print(list(ims))#[('BMW', 8.5), ('BENS', 8.3), ('AUDI', 7.9)]
#访问第二个key-value对
print(list(ims)[1])#('BENS', 8.3)
#获取字典中所有的key,返回一个dict_keys对象
kys=cars.keys()
print(type(kys))#
#将dict_keys转换成列表
print(list(kys))#['BMW', 'BENS', 'AUDI']
#访问第二个key
print(list(kys)[1])#BENS
#获取字典中所有的values,返回一个dict_values对象
vals=cars.values()
print(type(vals))#
#将dict_values转换成列表
print(list(vals))#[8.5, 8.3, 7.9]
#访问第二个value
print(list(vals)[1])#8.3

从上面的代码可以看出,程序调用字典的items()、keys()、values()方法之后,都需要调用list()函数将它们转换成列表,这样即可把这三个方法的返回值转换成列表。

pop()方法用于获取指定key对应的value,并删除这个key-value对。

print(cars.pop('AUDI'))#7.9
print(cars)#{'BMW': 8.5, 'BENS': 8.3}

popitem()方法用于随机弹出字典中的一个key-value对。

提示:此处随机其实是假的,正如列表的pop()方法总是弹出列表中的最后一个元素,实际上字典的popitem()其实也是弹出字典的最后一个key-value对。由于字典存储key-value对的顺序是不可知的,因此开发者感觉字典的popitem()方法是“随机”弹出的,但实际上字典的popitem()方法总是弹出底层存储的最后一个key-value对。

print(cars)#{'AUDI': 7.9, 'BENS': 8.3, 'BMW': 8.5}
#弹出字典最底层存储的最后一个key-value对
print(cars.popitem())#('BMW', 8.5)
print(cars)#{'AUDI': 7.9, 'BENS': 8.3}

由于实际上popitem弹出的就是一个元组,因此程序完全可以通过序列解包的方式用两个变量分别接收key和value。

#将弹出项的key赋值给k,value赋值给v
k,v=cars.popitem()
print(k,v)#BENS 8.3

setdefault()方法也用于根据key来获取对应的value的值。但方法有一个额外的功能——当程序要获取的key在字典中不存在,该方法会先为这个不存在的key设置一个默认的value,然后再返回该key对应的value。总之,setdefault()方法总能返回key对应的value——如果key-value对存在,则直接返回该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)#{'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9, 'PORSCHE': 9.2}
#设置默认值,该key在dict中存在,不会修改dict内容
print(cars.setdefault('BMW',3.4))#8.5
print(cars)#{'BMW': 8.5, 'BENS': 8.3, 'AUDI': 7.9, 'PORSCHE': 9.2}

fromkeys()方法使用给定的多个key创建字典,这些key对应的value默认都是None;也可以额外传入一个参数作为默认的value。该方法一般不会使用字典对象调用(没什么意义),弹出会使用dict类直接调用。

#使用列表创建包含两个key的字典
a_dict=dict.fromkeys(['a','b'])
print(a_dict)#{'a': None, 'b': None}
#使用元组创建包含两个key的字典
b_list=dict.fromkeys((13,17))
print(b_list)#{13: None, 17: None}
#使用元组创建包含两个key的字典,指定默认的value
c_dict=dict.fromkeys((13,17),'good')
print(c_dict)#{13: 'good', 17: 'good'}

3.4.5 使用字典格式化字符串

要格式化的字符串中包含多个变量,后面就需要按顺序给出多个变量,这种方式对于字符串模板中包含少量变量的情形是合适的,但如果字符串模板中包含大量变量,这种按顺序提供变量的方式则有些不合适。可改为在字符串模板中按key指定变量,然后提供字典为字符串模板中的key设置值。

#在字符串模板使用key
temp='书名是:%(name)s,价格是:%(price)010.2f,出版社是:%(publish)s'
book={'name':'crazyit','price':88.9,'publish':'电子社'}
#使用字典为字符串模板中的key传入值
print(temp % book)#书名是:crazyit,价格是:0000088.90,出版社是:电子社
book={'name':'crazyit','price':78.9,'publish':'电子社'}
#使用字典为字符串模板中的key传入值
print(temp % book)#书名是:crazyit,价格是:0000078.90,出版社是:电子社

你可能感兴趣的:(python,python)