第4章 操作列表
4.1 遍历整个列表
可使用Python中的 for 循环,遍历列表的所有元素,对每个元素执行相同的操作。
4.1.1 深入地研究循环
1 magicians = ['alice', 'david', 'carolina'] 2 for magician in magicians: 3 print(magician) 4 """ 5 alice 6 david 7 carolina 8 """
①行2的运作机制:从列表 magicians 中取出一个名字,并将其存储在变量 magician 中。然后打印前面存储到变量 magician 中的名字。之后循环直到遍历magicians。
②循环这种概念很重要,因为它是让计算机自动完成重复工作的常见方式之一。
③使用单数和复数式名称,可帮助你判断代码段处理的是单个列表元素还是整个列表。
4.1.2 在 for 循环中执行更多的操作
1 magicians = ['alice', 'david', 'carolina'] 2 for magician in magicians: 3 print(magician.title() + ", that was a great trick!") 4 print("I can't wait to see your next trick," + magician.title() + ". ") 5 """ 6 Alice, that was a great trick! 7 I can't wait to see your next trick,Alice. 8 9 David, that was a great trick! 10 I can't wait to see your next trick,David. 11 12 Carolina, that was a great trick! 13 I can't wait to see your next trick,Carolina. 14 """
①在代码行 for magician in magicians 后面,每个缩进的代码行都是循环的一部分,且将针对列表中的每个值都执行一次。因此,可对列表中的每个值执行任意次数的操作。如行3、4
4.1.3 在 for 循环结束后执行一些操作
1 magicians = ['alice', 'david', 'carolina'] 2 for magician in magicians: 3 print(magician.title() + ", that was a great trick!") 4 print("I can't wait to see your next trick," + magician.title() + ". ") 5 print("That you, everyone. That was a great magic show!") 6 """ 7 Alice, that was a great trick! 8 I can't wait to see your next trick,Alice. 9 10 David, that was a great trick! 11 I can't wait to see your next trick,David. 12 13 Carolina, that was a great trick! 14 I can't wait to see your next trick,Carolina. 15 16 That you, everyone. That was a great magic show! 17 """
① 在 for 循环后面,没有缩进的代码都只执行一次,而不会重复执行。如行5.
4.2 避免缩进错误
①Python根据缩进来判断代码行与前一个代码行的关系。
②当你开始编写必须正确缩进的代码时,需要注意一些常见的缩进错误。
4.2.1 忘记缩进
1 magicians = ['alice', 'david', 'carolina'] 2 for magician in magicians: 3 print(magician) 4 """ 5 File "E:/python/代码/caogao.py", line 3 6 print(magician) 7 ^ 8 IndentationError: expected an indented block 9 """
①对于位于 for 语句后面且属于循环组成部分的代码行,一定要缩进。
②for语句后没有缩进的代码行,会报错。如行3
4.2.2 忘记缩进额外的代码行
1 magicians = ['alice', 'david', 'carolina'] 2 for magician in magicians: 3 print(magician.title() + ", that was a great trick!") 4 print("I can't wait to see your next trick, " + magician.title() + ". ") 5 """ 6 Alice, that was a great trick! 7 David, that was a great trick! 8 Carolina, that was a great trick! 9 I can't wait to see your next trick, Carolina. 10 """
①当循环忘记缩进额外的代码行,循环能够运行而不会报告错误,但结果可能会出乎意料,会出现逻辑错误。如行4
4.2.3 不必要的缩进
1 message = "Hello Python world!" 2 print(message) 3 """ 4 File "E:/python/代码/caogao.py", line 2 5 print(message) 6 ^ 7 IndentationError: unexpected indent 8 """
①不小心缩进了无需缩进的代码行,Python会报错,逻辑错误。
②为避免意外缩进错误,请只缩进需要缩进的代码。在前面编写的程序中,只有要在 for 循环中对每个元素执行的代码需要缩进。
4.2.4 循环后不必要的缩进
1 magicians = ['alice', 'david', 'carolina'] 2 for magician in magicians: 3 print(magician.title() + ", that was a great trick!") 4 print("I can't wait to see your next trick, " + magician.title() + ". ") 5 print("Thank you everyone, that was a great magic show!") 6 """ 7 Alice, that was a great trick! 8 I can't wait to see your next trick, Alice. 9 10 Thank you everyone, that was a great magic show! 11 David, that was a great trick! 12 I can't wait to see your next trick, David. 13 14 Thank you everyone, that was a great magic show! 15 Carolina, that was a great trick! 16 I can't wait to see your next trick, Carolina.
①缩进了应在循环结束后执行的代码,大多数情况下,这只会导致逻辑错误。
4.2.5 遗漏了冒号
1 magicians = ['alice', 'david', 'carolina'] 2 for magician in magicians 3 print(magician) 4 """ 5 File "E:/python/代码/caogao.py", line 2 6 for magician in magicians 7 ^ 8 SyntaxError: invalid syntax 9 """
①遗漏了冒号,将导致语法错误。如行2
1 #习题1 2 """ 3 比萨:想出至少三种你喜欢的比萨,将其名称存储在一个列表中,再使用 for循环将每种比萨的名称都打印出来。 4 修改这个 for 循环,使其打印包含比萨名称的句子,而不仅仅是比萨的名称。对于每种比萨,都显示一行输出,如“I like pepperoni pizza”。 5 在程序末尾添加一行代码,它不在 for 循环中,指出你有多喜欢比萨。输出应包含针对每种比萨的消息,还有一个总结性句子,如“I really love pizza!”。 6 """ 7 pizzas = ['爱尔良披萨', '水果披萨', '双拼披萨'] 8 for pizza in pizzas: 9 print(pizza) 10 print("我喜欢" + pizza + "。 ") 11 print("我非常喜欢披萨!") 12 13 #练习2 14 """ 15 动物:想出至少三种有共同特征的动物,将这些动物的名称存储在一个列表中,再使用 for 循环将每种动物的名称都打印出来。 16 修改这个程序,使其针对每种动物都打印一个句子,如“A dog would make a great pet”。 17 在程序末尾添加一行代码,指出这些动物的共同之处,如打印诸如“Any of these animals would make a great pet!”这样的句子。 18 """ 19 pets = ['猫', '兔子', '狗'] 20 for pet in pets: 21 print(pet) 22 print(pet + "是种很好的宠物。 ") 23 print("这些宠物都是不错的宠物。")
4.3 创建数值列表
列表非常适合用于存储数字集合,而Python提供了很多工具,可帮助你高效地处理数字列表。
4.3.1 使用函数 range()
1 for value in range(1, 5): 2 print(value) 3 """ 4 1 5 2 6 3 7 4 8 """ 9 for value in range(1, 6): 10 print(value) 11 """ 12 1 13 2 14 3 15 4 16 5 17 """
①range() 函数能够生成一系列的数字。如行1、9,使用函数range() 来打印一系列的数字。
②使用 range() 时,如果输出不符合预期,请尝试将指定的值加1或减1。
4.3.2 使用 range() 创建数字列表
1 numbers = list(range(1,6)) 2 print(numbers) 3 # [1, 2, 3, 4, 5] 4 even_numbers = list(range(2,11,2)) 5 print(even_numbers) 6 # [2, 4, 6, 8, 10] 7 squares = [] 8 for value in range(1, 11): 9 square = value**2 10 squares.append(square) 11 print(squares) 12 # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 13 squares = [] 14 for value in range(1, 11): 15 squares.append(value**2) 16 print(squares) 17 # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
①创建数字列表,通过使用函数 list() 将 range() 的结果直接转换为列表。将 range() 作为list() 的参数,输出将为一个数字列表。如行1
②使用函数 range() 时,还可指定步长。如行4
使用函数 range() 几乎能够创建任何需要的数字集。如行8、14
4.3.3 对数字列表执行简单的统计计算
1 digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] 2 print(min(digits)) 3 print(max(digits)) 4 print(sum(digits)) 5 """ 6 0 7 9 8 45 9 """
①有几个专门用于处理数字列表的Python函数。如行2、3、4,数字列表的最大值、最小值和总和。
4.3.4 列表解析
1 squares = [value**2 for value in range(1,11)] 2 print(squares) 3 # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
列表解析格式:
①指定一个描述性的列表名,如 squares 。
②指定一对括号,将最终列表中的值储存进去。
③在括号内定义一个表达式,用于生成你要存储到列表中的值。如表达式为 value**2 ,它计算平方值。
④编写一个 for 循环,用于给表达式提供值。如 for value in range(1,11) ,它将值1~10提供给表达式 value**2 。
⑤请注意,这里的 for语句末尾没有冒号。
1 #习题1 2 #使用一个 for 循环打印数字 1~20(含)。 3 for value in range(1, 21): 4 print(value) 5 6 #习题2 7 #创建一个列表,其中包含数字 1~1 000 000,再使用一个 for 循环将这些数字打印出来(如果输出的时间太长,按 Ctrl + C停止输出,或关闭输出窗口)。 8 numbers = list(range(1, 1000001)) 9 for number in numbers: 10 print(number) 11 12 #习题3 13 """ 14 计算 1~1 000 000 的总和:创建一个列表,其中包含数字 1~1 000 000,再使用min() 和 max() 核实该列表确实是从 1开始,到 1 000 000结束的。另外,对这个列表调用函数 sum() ,看看 Python将一百万个数字相加需要多长时间。 15 """ 16 numbers = list(range(1, 1000001)) 17 print(min(numbers)) 18 print(max(numbers)) 19 print(sum(numbers)) 20 21 #习题4 22 # 奇数:通过给函数 range() 指定第三个参数来创建一个列表,其中包含 1~20的奇数;再使用一个 for 循环将这些数字都打印出来。 23 for number in range(1,21,2): 24 print(number) 25 26 #习题5 27 # 3 的倍数:创建一个列表,其中包含 3~30内能被 3整除的数字;再使用一个 for循环将这个列表中的数字都打印出来。 28 for number in range(3,31,3): 29 print(number) 30 31 #习题6 32 """ 33 立方:将同一个数字乘三次称为立方。例如,在 Python 中,2 的立方用 2**3表示。请创建一个列表,其中包含前 10个整数(即 1~10)的立方,再使用一个 for 循环将这些立方数都打印出来。 34 """ 35 cubes = [] 36 for value in range(1, 11): 37 cubes.append(value**3) 38 print(cubes) 39 for cube in cubes: 40 print(cube) 41 42 #习题7 43 # 立方解析:使用列表解析生成一个列表,其中包含前 10个整数的立方。 44 cubes = [value**3 for value in range(1, 11)] 45 print(cubes)
4.4 使用列表的一部分
通过使用切片处理列表的部分元素。
4.4.1 切片
1 players = ['charles', 'machael', 'michael', 'florence', 'eli'] 2 print(players[0:3]) 3 #['charles', 'machael', 'michael'] 4 print(players[1:4]) 5 #['machael', 'michael', 'florence'] 6 print(players[:4]) 7 #['charles', 'machael', 'michael', 'florence'] 8 print(players[2:]) 9 #['michael', 'florence', 'eli'] 10 print(players[-3:]) 11 #['michael', 'florence', 'eli']
①通过指定第一个元素和最后一个元素的索引,创造切片。如行2、4
②切片索引在到达指定的第二个索引前面的元素后停止。但因列表的索引从0开始,所以并不需要-1。如行2、4
③列表切片的返回结果也是列表。如行2、4
④切片可以生成列表的任何子集。如行4
⑤没有指定第一个索引,Python将自动从列表开头开始。如行6
⑥没有指定最后一个索引,Python将自动到列表末尾结束。如行8
⑦负数索引返回离列表末尾相应距离的元素。如行10
4.4.2 遍历切片
1 players = ['charles', 'machael', 'michael', 'florence', 'eli'] 2 print("Here are the first three players on my team:") 3 for player in players[:3]: 4 print(player.title()) 5 """ 6 Here are the first three players on my team: 7 Charles 8 Machael 9 Michael 10 """
①通过在 for 循环中使用切片,遍历列表的部分元素。如行3、4
4.4.3 复制列表
1 my_foods = ['pizza', 'falafel', 'carrot cake'] 2 friend_foods = my_foods[:] 3 print("My favorite foods are:") 4 print(my_foods) 5 print(" My friend's favorite foods are:") 6 print(friend_foods) 7 """ 8 My favorite foods are: 9 ['pizza', 'falafel', 'carrot cake'] 10 11 My friend's favorite foods are: 12 ['pizza', 'falafel', 'carrot cake'] 13 """ 14 my_foods.append('cannoli') 15 friend_foods.append('ice cream') 16 print("My favorite foods are:") 17 print(my_foods) 18 print(" My friend's favorite foods are:") 19 print(friend_foods) 20 """ 21 My favorite foods are: 22 ['pizza', 'falafel', 'carrot cake', 'cannoli'] 23 24 My friend's favorite foods are: 25 ['pizza', 'falafel', 'carrot cake', 'ice cream'] 26 """ 27 my_foods = ['pizza', 'falafel', 'carrot cake'] 28 friend_foods = my_foods 29 my_foods.append('cannoli') 30 friend_foods.append('ice cream') 31 print("My favorite foods are:") 32 print(my_foods) 33 print(" My friend's favorite foods are:") 34 print(friend_foods) 35 """ 36 My favorite foods are: 37 ['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream'] 38 39 My friend's favorite foods are: 40 ['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream'] 41 """
①通过切片复制的方法,能根据既有列表创建全新的列表。如行2
②通过创建一个包含整个列表的切片,可以复制列表,方法是同时省略起始索引和终止索引( [:] )。如行2
③直接将一个列表复制给另外一个列表 ,不能得到两个列表。如行28
④直接将一个列表复制给另外一个列表,新旧列表,指向同一个列表。修改其中任何一个都会改变列表。如行28
⑤使用切片复制了列表,才能创造全新的列表,修改其中一个列表,不会改变另一个列表,如行14、15
1 #习题1 2 """ 3 切片:选择你在本章编写的一个程序,在末尾添加几行代码,以完成如下任务。 4 打印消息“The first three items in the list are:”,再使用切片来打印列表的前 5 三个元素。 6 打印消息“Three items from the middle of the list are:”,再使用切片来打印列 7 表中间的三个元素。 8 打印消息“The last three items in the list are:”,再使用切片来打印列表末尾的 9 三个元素。 10 """ 11 players = ['charles', 'machael', 'michael', 'florence', 'eli'] 12 print("The first three items in the list are:") 13 print(players[0:3]) 14 print("Three items from the middle of the list are:") 15 print(players[1:4]) 16 print("The last three items in the list are:") 17 print(players[-3:]) 18 """ 19 The first three items in the list are: 20 ['charles', 'machael', 'michael'] 21 Three items from the middle of the list are: 22 ['machael', 'michael', 'florence'] 23 The last three items in the list are: 24 ['michael', 'florence', 'eli'] 25 """ 26 27 #习题2 28 """ 29 你的比萨和我的比萨:在你为完成练习 4-1而编写的程序中,创建比萨列表的副本, 30 并将其存储到变量 friend_pizzas 中,再完成如下任务。 31 在原来的比萨列表中添加一种比萨。 32 在列表 friend_pizzas 中添加另一种比萨。 33 核实你有两个不同的列表。为此,打印消息“My favorite pizzas are:”,再使用一个 34 for 循环来打印第一个列表;打印消息“My friend’s favorite pizzas are:”, 35 再使用一个 for 循环来打印第二个列表。核实新增的比萨被添加到了正确的列表中。 36 """ 37 my_pizzas = ['爱尔良披萨', '水果披萨', '双拼披萨'] 38 friend_pizzas = my_pizzas[:] 39 print(friend_pizzas) 40 my_pizzas.append('德国风味披萨') 41 friend_pizzas.append('日式披萨') 42 print("My favorite pizzas are:") 43 for pizza in my_pizzas: 44 print(pizza) 45 print("My friend’s favorite pizzas are:") 46 for pizza in friend_pizzas: 47 print(pizza) 48 """ 49 ['爱尔良披萨', '水果披萨', '双拼披萨'] 50 My favorite pizzas are: 51 爱尔良披萨 52 水果披萨 53 双拼披萨 54 德国风味披萨 55 My friend’s favorite pizzas are: 56 爱尔良披萨 57 水果披萨 58 双拼披萨 59 日式披萨 60 """ 61 62 #习题3 63 """ 64 使用多个循环:在本节中,为节省篇幅,程序 foods.py的每个版本都没有使用 65 for 循环来打印列表。请选择一个版本的 foods.py,在其中编写两个 for 循环, 66 将各个食品列表都打印出来。 67 """ 68 my_foods = ['pizza', 'falafel', 'carrot cake'] 69 friend_foods = my_foods[:] 70 print("My favorite foods are:") 71 print(my_foods) 72 print(" My friend's favorite foods are:") 73 print(friend_foods) 74 my_foods.append('cannoli') 75 friend_foods.append('ice cream') 76 print("My favorite foods are:") 77 for food in my_foods: 78 print(food) 79 print("My friend’s favorite foods are:") 80 for food in friend_foods: 81 print(food) 82 """ 83 My favorite foods are: 84 ['pizza', 'falafel', 'carrot cake'] 85 86 My friend's favorite foods are: 87 ['pizza', 'falafel', 'carrot cake'] 88 My favorite foods are: 89 pizza 90 falafel 91 carrot cake 92 cannoli 93 My friend’s favorite foods are: 94 pizza 95 falafel 96 carrot cake 97 ice cream 98 """
4.5 元组
①列表是变化的、可以修改的数据集。
②元组是不可变的、不可修改的数据集。不能单独修改元组的元素,但可以将元组整体变量赋值改变。
4.5.1 定义元组
1 dimensions = (200, 50) 2 print(dimensions[0]) 3 # 200 4 print(dimensions[1]) 5 # 50 6 dimensions[0] = 250 7 """ 8 Traceback (most recent call last): 9 File "E:/python/代码/caogao.py", line 6, in <module> 10 dimensions[0] = 250 11 TypeError: 'tuple' object does not support item assignment 12 """
①元组用圆括号(())标识,与列表形式相似。如行1
②元组可以使用索引来访问其元素,与访问列表元素一样。如行2
③元组不可改变其元素值,不能给元组的元素赋值,试图改变会返回类型错误的报错消息。如行6
4.5.2 遍历元组中的所有值
dimensions = (200, 5) for dimension in dimensions: print(dimension) """ 200 5 """
①用 for 循环来遍历元组中的所有值。如行2
4.5.3 修改元组变量
1 dimensions = (200, 50) 2 print("Original dimensions:") 3 for dimension in dimensions: 4 print(dimension) 5 """ 6 Original dimensions: 7 200 8 50 9 """ 10 dimensions = (400, 100) 11 print(" Modified dimensions:") 12 for dimension in dimensions: 13 print(dimension) 14 """ 15 Modified dimensions: 16 400 17 100 18 """
①不能修改元组的元素,但给存储元组的变量重新赋值是合法的。需要修改元组元素,可重新定义整个元组。如行10
②相比于列表,由于元组元素不能改变,元组是更简单的数据结构。
4.6 设置代码格式
随着你编写的程序越来越长,有必要了解一些代码格式设置约定。请花时间让你的代码尽可能易于阅读;让代码易于阅读有助于你掌握程序是做什么的,也可以帮助他人理解你编写的代码。为确保所有人编写的代码的结构都大致一致,Python程序员都遵循一些格式设置约定。学会编写整洁的Python后,就能明白他人编写的Python代码的整体结构——只要他们和你遵循相同的指南。要成为专业程序员,应从现在开始就遵循这些指南,以养成良好的习惯。
4.6.1 格式设置指南
若要提出Python语言修改建议,需要编写Python改进提案(Python Enhancement Proposal,PEP)。PEP 8是最古老的PEP之一,它向Python程序员提供了代码格式设置指南。PEP 8的篇幅很长,但大都与复杂的编码结构相关。
Python格式设置指南的编写者深知,代码被阅读的次数比编写的次数多。代码编写出来后,调试时你需要阅读它;给程序添加新功能时,需要花很长的时间阅读代码;与其他程序员分享代码时,这些程序员也将阅读它们。
如果一定要在让代码易于编写和易于阅读之间做出选择,Python程序员几乎总是会选择后者。下面的指南可帮助你从一开始就编写出清晰的代码。
4.6.2 缩进
PEP 8建议每级缩进都使用四个空格,这既可提高可读性,又留下了足够的多级缩进空间。
在字处理文档中,大家常常使用制表符而不是空格来缩进。对于字处理文档来说,这样做的效果很好,但混合使用制表符和空格会让Python解释器感到迷惑。每款文本编辑器都提供了一种设置,可将输入的制表符转换为指定数量的空格。你在编写代码时应该使用制表符键,但一定要对编辑器进行设置,使其在文档中插入空格而不是制表符。
在程序中混合使用制表符和空格可能导致极难解决的问题。如果你混合使用了制表符和空格,可将文件中所有的制表符转换为空格,大多数编辑器都提供了这样的功能。
4.6.3 行长
很多Python程序员都建议每行不超过80字符。最初制定这样的指南时,在大多数计算机中,终端窗口每行只能容纳79字符;当前,计算机屏幕每行可容纳的字符数多得多,为何还要使用79字符的标准行长呢?这里有别的原因。专业程序员通常会在同一个屏幕上打开多个文件,使用标准行长可以让他们在屏幕上并排打开两三个文件时能同时看到各个文件的完整行。PEP 8还建议注释的行长都不超过72字符,因为有些工具为大型项目自动生成文档时,会在每行注释开头添加格式化字符。
PEP 8中有关行长的指南并非不可逾越的红线,有些小组将最大行长设置为99字符。在学习期间,你不用过多地考虑代码的行长,但别忘了,协作编写程序时,大家几乎都遵守PEP 8指南。在大多数编辑器中,都可设置一个视觉标志——通常是一条竖线,让你知道不能越过的界线在什么地方。
4.6.4 空行
要将程序的不同部分分开,可使用空行。你应该使用空行来组织程序文件,但也不能滥用;只要按本书的示例展示的那样做,就能掌握其中的平衡。例如,如果你有5行创建列表的代码,还有3行处理该列表的代码,那么用一个空行将这两部分隔开是合适的。然而,你不应使用三四个空行将它们隔开。
空行不会影响代码的运行,但会影响代码的可读性。Python解释器根据水平缩进情况来解读代码,但不关心垂直间距。