本文目录
第4章 操作列表
学会创建列表之后,对列表中的元素进行各种操作,才是真正要学习的。而一个列表可能包含成千上万甚至更多的元素,要对这些元素进行统一操作,不可能逐一去写重复代码。就一个简单的输出而言,如果每个元素都要print()输出一次,1000个元素就意味着要写一千行重复的代码,所以要用到各种操作列表的工具。
4.1遍历整个列表(for循环)
在Python中,需要遍历列表中的所有元素,或者对所有元素执行相同处理时,用for循环会很方便。
for 临时变量名 in 列表名 :
循环体代码必须缩进,如print等各种处理
循环体代码必须缩进,循环体可以很大,可以执行任何操作
循环结束后不再缩进代码
airenmen=['老婆','儿子','妈妈']
for airen in airenmen : # for 后面是用于关联列表元素的临时变量, in 后面是要遍历的列表
# 这里的 冒号 : 非常重要!!!它告诉Python下一行是循环体代码的第一行
print(airen) #循环体代码必须缩进,否则不会循环执行,甚至会报错
print(f"临时变量值此时为:{airen}") #不缩进的代码不属于循环体,只会在for循环之后执行一次
4.1.1 循环语法说明
- 在代码
for airen in airenmen :
中,Python从列表airenmen
中获取第一个值老婆
,并将其与循环本身的临时变量airen
进行关联; - 而
print(airen)
则将airen
获得的关联值打印出来; - 这个循环体只有一行,且列表
airenmen
中不止1个元素; - 因此,执行本次输出后,将回到第一行再次执行,并关联第二个元素
儿子
,之后再一次执行循环体,也就是print()
函数; - 直至列表中所有元素被遍历,才会退出循环,并继续执行循环外的其他代码。
- 上例的输出结果为:
老婆
儿子
妈妈
临时变量值此时为:妈妈
从最后一行输出结果可以看出,临时变量airen
在循环结束时,保留的最终结果是:妈妈。
注意!for循环语句的末尾必须有冒号:
循环体的每一行代码都一定要正确缩进
Python认可的缩进是4个空格
4.1.2 循环可以很复杂
从上例就能看出,循环体能做很多事,而且,循环体也可以不止一行,能在每一次循环中执行各种需要的代码,让循环实现很多的功能,举个简单的例子,仅print()函数,就可以实现对列表中的每一位爱人说几句话,而循环结束后,可以再继续向所有人有所表达。如:
airenmen=['老婆','儿子','妈妈']
for airen in airenmen : # 冒号 :很重要!
print(f"{airen},我爱你!") #对每位爱人说一句话
print(f"亲爱的{airen},我永远爱你!\n") #对每位爱人说第二句话
print(f"我永远爱你们,感谢你们这么多年对我的理解和包容。") #循环结束,向所有爱人致谢
这个循环会向三位爱人分别说两句话,并在第二句之后换行,总共输出六句话;循环结束后再向所有爱人致谢。
这里拓展一下,很明显,for循环是可以嵌套多层使用的。比如来分析一下爱人们的爱好:
airenmen=['老婆','儿子','妈妈']
aihaos=['摄影','烹饪','弹琴'] #列表名用负数形式比较容易和变量名区分,即使是拼音命名
for airen in airenmen : #第一层循环,每次获取一位爱人的名字
for aihao in aihaos : #第二层循环,每次为爱人匹配一项爱好
print(f"{airen}真的喜欢{aihao}吗?") #第二层循环中输出每位爱人和每种爱好的关联
这个例子将会输出总共9行结果,每位爱人3行,3位爱人分别关联3种不同的爱好。结果如:
老婆真的喜欢摄影吗?
老婆真的喜欢烹饪吗?
老婆真的喜欢弹琴吗?
儿子真的喜欢摄影吗?
儿子真的喜欢烹饪吗?
儿子真的喜欢弹琴吗?
妈妈真的喜欢摄影吗?
妈妈真的喜欢烹饪吗?
妈妈真的喜欢弹琴吗?
4.2循环中要注意避免的问题
首先,冒号:
是非常重要的,必须有冒号,循环语法才完整,对于Python来说,冒号的下一行,就是循环体的第一行;
然后是缩进,尤其是多层嵌套时,或者将循环放在其他缩进的代码块中时,缩进非常重要。Python并不使用括号来包围和限制循环体,而是单纯的凭借缩进代码是识别,每层缩进为4个空格,这是必须养成的编程习惯。
在不恰当的地方进行缩进或者未在恰当的地方缩进,都会造成错误。有些错误Python可以识别,甚至能给与提示,但有些语法上正确的缩进错误,就不会被Python发现,而且能顺利执行,但是结果往往并不是预期的,这就是语法正确但逻辑错误。良好的习惯很重要,因为有些错误可能仅仅是一个字符或者一个空格造成的,但是在排查修改的时候却要耗费大量时间和精力。
4.3创建数值列表
需要存储一组数值的原因很多,列表非常适合用于存储数值集合,Python有很多工具可以高效处理数值列表
4.3.1 使用range()函数
range()函数用于生成一系列数值,并且可以通过不同参数生成不同数值,再配合其他代码,几乎可以创造出任何形式的数列。
range(参数1,参数2,参数3)
for shuzhi in range(1,6): # range()函数可以生成一系列数值。不同参数产生不同结果,
# 第一参数1表示遍历数值的起始,即1,第二参数6表示遍历数值的结束,即6,所以,
# 这个range()函数循环会产生从1至6之间的自然数,不过,这里并不返回123456,
# 因为“差一”问题,循环遇到6就结束,而并不包含6,要包含6的话第二参数应为7)。
print(shuzhi) # 忘记缩进了笨笨……,再说一次,循环体代码必须缩进一段(4个空格)
# range()函数从第一个参数开始,到第二个参数值时停止,不会包含第二个值;
for shuzhi in range(6):
print(f"\t{shuzhi}")
# 当range()函数只带有一个参数时,等于第一参数为默认值:0,
# 这里的如range(6),其实就是range(0,6)将输出从0到5。
4.3.2 使用range()函数和list()函数创建数值列表
可以使用range()
函数作为参数,用list()
函数可以将range()
的结果转换成一个数值列表。
数列名 = list(参数,这里是另一个函数range())
shulie = list(range(1,13))
# 即,使用list()函数生成数值列表,而生成规则,则由作为其参数的range()函数决定
print(shulie)
shulie=list(range(0,21,3))
# range()函数可以有第三个参数,用来指定遍历数值时的步长,本例生成一个差为3的等差数列
print(shulie)
# 因为是差3,所以0,21并不会输出21,到18就会结束,要输出21就要用0,22
配合不同参数条件range()函数几乎可以创造任意形式的数值组合,如下创建一个1-10的自然数平方的数列
shulie=list(range(1,11))# 创建一个1到10的自然数列表
print(shulie)
for pingfang in shulie:# 在该列表中循环取值
pingfang = pingfang**2# 将每次循环取到的值平方后赋值给变量自己
print(pingfang)# 每次循环都输出当前变量的值,亦即其平方结果
上面这几行是自己在看教材代码之前尝试写的,写完发现自己犯了逻辑错误,代码是可以正常执行,但结果是输出了1-10的平方值,而不是一个包含这些值的数值列表,下面是参考教材中的正确方法后写的。
pingfang=[] #创建一个空数列
for shuzi in range(1,11) : # 利用range()函数进行1到10的自然数循环
jieguo = shuzi ** 2 # 每次循环都将当前自然数的平方赋值给临时变量
print(f"\t{jieguo}")# 每次循环输出当前临时变量的值
pingfang.append(jieguo) # 每次循环都将平方后临时变量的值追加到列表末尾
print(pingfang) # 循环结束后输出最终的数值列表
上面是比较老实(或者说比较笨拙)的写法,下面这个可以跳过创建变量并计算赋值的过程,而采用计算同时追加到列表的简单方法。
shulie = []# 创建空列表
for shuzi in range(1,11):# 在1-11范围内循环自然数
shulie.append(shuzi*2+1)# 每次循环将平方结果直接追加到数列末尾
print(shulie)# 检验当前数列内容
print(shulie)
这种方法明显可以让代码更简洁,有时候易懂更好,有时候则简洁更好,灵活掌握即可。
4.3.3 对数值列表执行简单的统计计算
这三个函数min()、max()、sum()
可以对数值列表进行一些简单的处理。
函数名(数值列表名)
# min()、max()和sum(),这三个函数工具可以返回列表中:最小值、最大值和数值总和。如:
print(f'\t数列pingfang的最小值:{min(pingfang)}')
print(f'\t数列shulie的最大值:{max(shulie)}')
print(f'\t数列shulie的所有元素之和:{sum(shulie)}')
4.3.4 列表推导式(list comprehension)
列表推导式是一个精简版的列表生成方式,它将列表命名、数值规律算式、取值范围,以及追元素都揉进一句for循环中,只要一行代码就可以实现前面的生成数值列表。新手虽然不太容易掌握,但还是很高效的,学会之后也更容易学习别人的代码。
列表名 = [ 数值规律算式 for 临时变量名 in range(循环的基本取值范围) ]
推导式中的for循环不要冒号:
tuidaoliebiao = [ shuzi*3/2+1 for shuzi in range(1,11) ]
# 这一行会对1-10之间的每个自然数进行*3/2+1的运算并将结果一一追加到
# 数值列表tuidaoliebiao的末尾
print(tuidaoliebiao)
练习题1:创建一个包含1~1000000的自然数列并打印出来
baiwan=[ziranshu for ziranshu in range(1,1000001)]
#利用推导式,一行搞定。因为是自然数列,无需任何计算,所以计算部分只有变量名本身。
print(baiwan)
本例输出结果为:[1,2,3…1000000]。输出时间太长可以随时在终端用
Ctrl+C
终止输出(在我老旧的机器上用了大约5秒)。
练习题2:求1~1000000(含1000000)之间所有奇数的和
baiwanjishu=[jishu for jishu in range(1,1000001,2)]
# 同样的推导式,只要增加步长2的参数,即可获得1-100万之间所有的奇数。
print(f"\t检查,数列最小值为:{min(baiwanjishu)}")
print(f"\t检查,数列最大值为:{max(baiwanjishu)}")
print(f"\n结果:1到100万之间所有奇数的和为:{sum(baiwanjishu)}")
4.4 使用列表的一部分
这部分学习处理列表中的部分元素,而非全部。
4.4.1 切片(Slice)
列表的切片,与range()
函数一样,也支持3个参数,参数用方括号[]
包围,并以冒号:
分隔,Python将返回自第一个参数起,到第二个参数止的所有元素。
列表名 [ 第一参数 , 第二参数 , 第三参数 ]
这里同样要注意差一问题,索引从0开始,且到第二个参截止,并不包含它。第三个参数用于控制访问的步长。
如,访问列表的第2~4这三个元素,使用的索引值(即前两个参数)为1:4
print(pingfang[1:4])
省略第一个参数,则取其默认值,从索引0,也就是列表第一个元素开始。
注意!在切片参数中,第一个参数可以省略,但第一个冒号
:
不能省略。
print(pingfang[:4])
print(pingfang[4])# 没有冒号将输出列表的第5个元素,而不是前4个。
省略第二个参数,则从第一个参数指定的索引开始,直至列表末尾。
print(pingfang[2:])# 道理同上,这个冒号也必须有。
切片同样可以使用负数索引,从后向前访问。如要获取列表的最后三项:
print(pingfang[-3:])
切片的第三个参数,用法与range()函数中的一致,用于决定遍历元素时的步长。
如下面,从头开始访问列表,每隔2个索引取一个元素,直至末尾。
print(pingfang[0::3])
4.4.2 遍历切片
遍历切片的方法与遍历列表一致,只需增加切片参数即可。如要遍历列表中的最后5个元素:
for shuzhi in pingfang[-5:] :
print(shuzhi)
4.4.3 复制列表
可以根据需要,将整个列表,或者例表中的部分切片复制到一个新的列表。
复制完整列表,也要使用切片参数,不过,不填写参数只要冒号:
而已。而带有实际参数则复制指定切边到新列表。
xinpf=pingfang[:]# 新列表xinpf将于pingfang的内容完全一致
bufen=pingfang[-5:]# 新列表bufen只包含pingfang的最后5个元素
需要注意的是,直接用变量名赋值是无法赋值列表的。如:
fuzhibiao = pingfang
这并不能创建一个名为fuzhibiao的新列表,实际上是等于将两个变量名都关联到同一个列表,列表本身的变化将同时影响fuzhibiao和pingfang这两个变量。
以后可能会出现两个变量关联到同一个值从而产生一些作用的情况,目前为止,这是没有意义的。
4.5 元组(tuple)
列表适合存放运行期间产生变化的数据集,而元组,则适合存放那些运行期间不可变的数据。
4.5.1 定义元组
定义元组的方法与列表类似,只是采用了圆括号()
包围,并以逗号,
分隔。访问与遍历元组的方式也于列表的相关方法一样。
元组变量名 = ( 元素1,元素2,... )
当元组只含有一个元素时,也必须有逗号,
,如:pai=(3.14159,)
,这里的逗号必须有。
这里要注意的是,元组是无法单独修改其中元素的,例如.append()方法是不支持的,通过
变量名[索引值]
去修改一个元组的元素也是不行的。下面的这些做法都会报错。
pingfang[0]=9
pingfang.append(9)
4.5.2 遍历元组
这与遍历元素一样,for循环即可。
4.5.3 修改元组变量
元组的单个元素不能直接修改,但是在需要时可以通过重新定义整个元组来改变其中的元素,甚至可以改变原有的数据类型和元素数量,总之是两个完全不同的元组。例如:
shenti=(176,50)
print(f"身高:{shenti[0]}cm\t体重:{shenti[1]}kg")
shenti=(110,45)
print(f"身高:{shenti[0]}cm\t体重:{shenti[1]}kg")
shenti=(13,110,45)
print(f"年龄:{shenti[0]} \t 身高:{shenti[1]} \t 体重:{shenti[1]}")
元组用来存放在一定周期内不会变化的值会更方便,因为他本身结构更简单。
4.6 关于PEP 8
PEP 8是关于编程习惯的一篇指南,其目的在于专业的程序员们都有大致统一的变成习惯,以便于代码的共享和协作。内容篇幅较长,有时间慢慢看吧。其中就包括了常说的:Python不用制表符而是用4个空格缩进;一行代码的长度应该在80字符以内……等等这些约定俗成的习惯。