第三章、操作列表
在上一章中,学习了如何创建简单的列表,还学习了如何操作列表元素。在本章节中,你将学习如何遍历整个列表,者只需要几行代码,无论列表有多长。循环让你能够对列表的每个元素都采取一个或一系列相同的措施,从而高效的处理任何长度的列表,包括包含数千乃至数百万个元素的列表。
3.1 遍历整个列表
你经常需要遍历列表的所有元素。对每个元素执行相同的操作。
magicians = ['alicc', 'david', 'carolina']
for magician in magicians:
print(magician)
3.2 避免缩进错误
Python 根据缩进来判断代码行与抢一个代码行的关系。在前面的示例中,向各位魔术师显示消息的代码行是 for 循环的一部分,因为他们缩进了。Python 通过使用缩进让代码更容易读;简单的说,它要求你使用缩进让代码整洁而结构清晰。在较长的 Python 程序中,你将看到缩进程度各不相同的代码块,这让你对程序的组织接口有大致的认识。
当你开始编写必须正确缩进的代码时,需要注意一些常见的缩进错误。例如,有时候程序员会将不需要缩进的代码块缩进,而对于必须缩进的代码块却忘了缩进,通过查看这样的错误示例,有助于你以后避开他们,以及在他们出现在程序中时进行修复。
3.2.1 忘记缩进
对于位于 for 语句后面且术语循环组成部分的代码行,一定要缩进,如果你忘记缩进,Python 会提醒你
indentationError: expected an indented block
3.2.2 忘记缩进额外的代码行
有时候,循环能够云心而不会报告错误,但结果可能会出乎意料。视图循环中执行多想任务,却忘记缩进其中的一些代码行时,就会出现这种情况。例如:如果忘记缩进循环中的第 2 行代码,就会出现这种情况
magicians=['alice', 'david', 'carolina']
for magician in magicians:
print(magician.title()) + ", that was a great trick!"
print("I can`t wait to see your next trick, " + magician.title() + ".\n")
像上面这种情况,这是一个逻辑错误。从语法上看,这些代码是合法的,但由于存在逻辑错误,结果并不符合预期,吐过你预期某项操作将针对每个列表元素都执行一次,但它只执行了一次,请确定是否忘记缩进。
3.2.3 不必要的缩进
如果你不小心缩进了无需缩进的代码行,Python 将指出这一点
message="hello"
print(message)
上面的程序中,print 语句不需要缩进,因为它并不属于前一行代码,因此 Python 将指出这种错误
IndentationError: unexpected indent
3.2.4 循环后不必要的缩进
如果你不小心缩进了应在循环结束后的代码,这些代码将针对每个列表元素重复执行,在有些情况下,这可能导致 Python 语法错误,但是在多数情况下,这只会导致逻辑错误。
3.2.5 遗漏了冒号
如果你在 for 循环中,遗漏了冒号,将导致语法错误,因为 Python 不知道你意欲何为。这种错误虽然易于消除,当并不那么容易发现。程序员为找出这样的单字符错误,花费的时间多得让人惊讶,因为这种错误通常我们的意料之外。
3.3 创建数值列表
需要存储一组是数字的原因有很多。例如在游戏中,需要跟踪每个角色的位置,还可能需要跟踪玩家的几个最高得分。在数据可视化中,处理的几乎都是由数字组成的集合。
列表非常适合用于存储数字集合,而 Python 提供了很多工具,可帮助你高效地处理数字列表。
3.3.1 使用函数 range()
Python 中函数 range() 让你能够轻松的生成一系列的数字
for value in range(1, 5):
print(value)
range() 函数会让你输出 1,2,3,4,但是不会输出 5。你可以理解为左闭右开的集合
3.3.2 使用 range() 创建数组列表
要创建数字列表,可使用函数 list() 将 range() 的结果直接转换为列表。如果将 range() 作为 list() 的参数,输出将为一个数字列表。我们打印了一系列数字,要将这些数字转换为一个列表,可使用 list()
numbers=list(range(1, 5))
print(numbers) # 输出:1 2 3 4
range() 函数还可以指定步长。
numbers=list(range(1, 10, 2))
print(numbers) # 输出:1 3 5 7 9
使用函数 range() 几乎能够创建任何需要的数字集,例如如何创建一个列表,其中包含前 10 个整数的平方呢?在 Python 中,两个星号(**)表示乘方运算。
squares=[]
for value in range(1, 11):
square = value ** 2
squares.append(square)
print(squares)
创建更复杂的列表时,可使用上述两种方法中的任何一种。有时候,使用临时变量会让代码更易读;而在其他情况下,这样做只会让代码无谓的边长。你首先应该考虑的是,编写清晰易懂且能完成所需功能的代码;等到审核代码时,在考虑采用更高效的方法。
3.3.3 对数字列表执行简单的统计计算
有几个专门用于处理数字列表的函数。例如你可以轻松的找出数字列表中的最大值、最小值和总和
numbers = range(1, 11)
min(numbers) # 输出:1
max(numbers) # 输出:10
sum(numbers) # 输出:55
3.3.4 列表解析
前面介绍的生成列表 squares 的方式包含三四行代码,而列表解析让你只需编写一行代码就能生成这样的列表。列表解析将 for 循环和创建新元素的代码合并成一行,并自动附加新元素。面向初学者的书籍并非都会介绍列表解析,这里之所以介绍,是因为等你开始阅读他人编写的代码时,很可能会遇到他们。
squares = [value**2 for value in range(1, 6)]
print(squares)
要使用这种语法,首先指定一个描述性的列表名,如 squares,然后指定一个左方括号,并定义一个表达式,用于生成你要存储到列表中值。在这个示例中,表达式要 value/*/2,它计算平方值。接下来,编写一个 for 循环,用于给表达式提供值,再加上右方括号。在这个示例中,for 循环为 for value in range(1, 6),它将值 1~5 提供给表达式 value//*2。请注意,这里的 for 语句末尾没有冒号。
3.4 使用列表的一部分
你可以处理列表的部分元素-Python 称之为切片。
3.4.1 切片
要创建切片,可指定要使用的第一个元素和最后一个元素的索引。与函数 range() 一样。Python在到达你指定的第二个索引前面的元素后停止。要输出列表中的前三个元素,需要指定索引 0~3 ,这将输出分别为0,1和 2 的元素。
players = ['aaa', 'bbb', 'ccc', 'ddd']
print(players[0:3]) # 输出:['aaa', 'bbb', 'ccc']
print(players[:3]) # 输出:['aaa', 'bbb', 'ccc']
print(player[2:]) # 输出:['ccc', 'ddd']
player[0:3]:表示该列表的一个切片,其中只包含三个元素。输出也是一个列表。
player[:3]:这里没有指定第一个索引,将自动从列表开头开始。
player[2:]:这里没有指定终止索引,将从指定的第一个索引知道列表末尾元素。
3.4.2 遍历切片
如果要遍历列表的部分元素,可在 for 循环中使用切片。
players = ['aaa', 'bbb', 'ccc', 'ddd']
print("Here are the first three players on my team:")
for player in player[:3]:
print(player.title())
3.4.3 复制列表
你经常需要根据既有列表创建全新的列表。下面来介绍复制列表的工作原理,以及复制列表提供极大帮助的一种情形。
要复制列表,可创建一个包含整个列表的切片,方法是同时省略起始索引。这让 Python 创建一个开始于第一个元素,终止于最后一个元素的切片,即可复制整个列表
players = ['aaa', 'bbb', 'ccc', 'ddd']
players_two = players[:]
players_two.append('eee')
players.append('fff')
print(players_two) # 输出:['aaa', 'bbb', 'ccc', 'ddd', 'eee']
print(players) # 输出:['aaa', 'bbb', 'ccc', 'ddd', 'fff']
players = ['aaa', 'bbb', 'ccc', 'ddd']
players_three = players
pplayers_two.append('eee')
players.append('fff')
print(players_two) # 输出:['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff']
print(players) # 输出:['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff']
从上面的例子中,我们可以看到。如果我们将旧列表复制到新列表中,然后往新旧列表分别加入一个元素,输出结果和我们想象中一样;但是,如果只是将旧列表赋值给新列表,然后往新旧列表分别加入一个元素,输出结果就是一样的结果,因为这两个变量都指向同一个列表。
3.5 元组
列表非常适合用于存储在程序运行期间可能变化的数据集。列表是可以修改的,这对处理网站的用户列表或游戏中的角色至关重要。然而,有时候你需要创建一系列不可修改的元素,元组可以满足这种需求,Python 将不能修改的值称为不可变的,而不可变的列表被称为元组。
3.5.1 定义元组
元组看起来犹如列表,但使用圆括号而不是方括号来标识。定义元组后,就可以使用索引来访问其中的元素,就像访问列表元素一样。
dimensions = (200, 50)
print(dimensions[0]) # 输出:200
print(dimensions[1]) # 输出:50
dimensions[0] = 250
# 此处尝试修改元组中的元素,导致 Python 返回类型错误信息,由于试图修改元组的操作的被禁止的,因此 Python 指出不能元组的元素赋值
# TypeError: 'tuple' object does not support item assignment
3.5.2 遍历元组中的所有元素
像列表一样,也可以使用 for 循环来遍历元组中的所有元素
dimensions = (200, 50)
for dimension in dimensions:
print(dimension)
3.5.3 修改元组变量
虽然不能修改元组的元素,但可以给存储元组的变量赋值。给元组变量赋值是合法的。
dimensions = (200, 50)
print("original dimensions:")
for dimension in dimensions:
print(dimension)
dimensions = (400, 100)
print("\nModified dimensions:")
for dimension in dimensions:
print(dimension)
3.6 设置代码格式
随着编写的代码越来越长,有必要了解一些代码格式设置的约定。请花时间让你的代码尽可能易于阅读;让代码易于阅读有助于你掌握程序是做什么的,也可以帮助他人理解你的代码。
为确保所有人编写的代码的结构都大致一致,Python 程序员都会准寻一些格式设置约定。学会编写整洁的 Python 后,就能明白他人编写的 Python 代码的整体结构—只要他们和你都遵守相同的指南。要想成为专业的程序员,应从刚开始学习编程的时候就遵守不同语言的这些规范,以养成良好的编码习惯。
3.6.1 格式设置指南
若要剔除 Python 语言修改建议,需要编写 Python 改进提案(Python Enhancement proposal,PEP)。PEP8 是最古老的 PEP 之一。他向 Python 程序员提供了代码格式设置指南。
Python 格式设置指南的编写者深知,代码被阅读的次数比编写的次数多。代码编写出来后,调试时你需要阅读它;给程序添加新功能时,需要花很长的时间阅读代码;与其他程序员分享代码时,这些程序员也将阅读他们。
如果一定要在让代码易于编写和易于阅读之间做出选择,Python 程序员几乎总是会选择后者。
3.6.2 缩进
PEP8 建议每级缩进都使用 4 个空格,这既可以提高可读性,又留下了足够的多级缩进空间。
在处理文档中,大家常常用制表符而不是空格来缩进。对于处理文档来说,这样做的效果很好,但混合使用制表符和空格会让 Python 解释器感到迷惑。每款文本编辑器都提供了一种设置,可将输入的制表符转换为指定数量的空格。你在编写代码时应该使用制表符键,但一定要对编辑器进行设置,使其在文档中插入空格而不是制表符。
在程序中混合使用制表符和空格可能会导致极难解决的问题。如果你混合使用了制表符和空格,可将文件中所有的制表符转换为空格,大多数编辑器都提供了这样的功能。
3.6.3 行长
很多语言都建议代码每行不超过 80 字符。最初指定这样的指南时,在大多数计算机中,终端窗口每行只能容纳 79 个字符;当前,计算机屏幕每行可容纳的字符多得多,为何还要使用 79 字符的标准行长呢?这里有别的原因。专业程序员通常会在同一个屏幕上打开多个文件,使用标准行长可以让让门在屏幕并排打开两三个文件时能同时看到各个文件的完整行。PEP8 还建议注释的行长都不超过 72 字符,因为有些工具为大型项目自动生成文档时,会在每行注释开头添加格式化字符。
3.6.4 空行
要将程序的不同部分分开,可以使用空行。你应该使用空行来组织程序文件,但也不能滥用;只要按照示例展示那样做,就能掌握其中的平衡。例如如果你有 5 行创建列表的代码,还有 3 行处理该列表的代码,那么用一个空行将这两部分隔开是合适的。然而,你不应使用三四个空行将他们分开。
空行不会影响代码的运行,但会影响代码的可读性。
第四章、IF 语句
4.1 一个简单的示例
cars = ['audi', 'bmw', 'toyota']
for car in cars:
if car == 'bmw':
print(car.upper())
else
print(car.title())
在上面的示例中,用 for 循环遍历一个列表,然后如果遍历的元素如果为’bmw’,那么将该元素全部大写输出,否则输出的元素只是首字母大写。
4.2 条件测试
每个 if 语句的核心都是一个值为 T/F 的表达式,这种表达式被称为条件测试。Python 根据条件测试的值来决定是否执行 if 语句中的代码。
4.2.1 检查是否相等
大多数条件测试都将一个变量的当前值同特定值进行比较。最简单的条件测试是检查变量的值方式是否与特定值相等
car = 'bmw'
# 使用两个等号(==)检查运算符两边的值是否相等
car == 'bwm' # 输出 False
4.2.2 检查是否相等时不考虑大写
在 Python 中检查是否相等时区分大小写。即两个大小写不同的值会被视为不相等
car = 'Audi'
car == 'audi' # 输出 False
# 如果大小写很重要,这种行为有其优点。但如果大小写无关紧要,而指向检查变量的值,可以将变量的值转换为小写后在进行比较。因为使用函数 lower() 不会改变存储在变量 car 中的值,因此进行这样的比较时不会影响原来的变量
car.lower() == 'audi'
4.2.3 检查是否不相等
要判断两个值是否不等,可结合使用惊叹号和等号(!=)
4.2.4 比较数字
age = 18
age < 18 # 输出 False
age <= 18 # 输出 True
age == 18 # 输出 True
age > 18 # 输出 False
age >= 18 # 输出 True
4.2.5 检查多个条件
要检查是否两个条件都为 True,可使用关键字 and 将两个条件测试合而为一;如果每个测试都通过了,整个表达式就为 True;如果至少有一个测试没有通过,整个表达式就返回 False。
关键字 or 也能够让你检查多个条件,但只要至少有一个条件满足,就能通过整个测试。仅当两个测试都没有通过时,才会返回 False。
4.2.6 布尔表达式
随着你对编程的了解越来越深入,将遇到术语布尔表达式。他就是条件测试的别名。与条件表达式一样,布尔表达式要么结果为 True,要么为 False。
4.3 IF 语句
理解条件测试号后,就可以开始编写 IF 语句了,IF 语句有很多种,选择使用哪种取决于要测试的条件数。
4.3.1 简单的 IF 语句
最简单的 IF 语句只有一个测试和一个操作
if conditional_test:
do something
在第一行中,可包含任何条件测试,而在紧跟在测试后面的缩进代码块中,可执行任何操作。如果条件测试的结果为 True,Python 就会执行紧跟在 IF 语句后面的代码,否则 Python 将忽略这些代码。
在 IF 语句中,缩进的作用于 for 循环中相同。如果测试通过了,将执行 if 语句后面所有缩进的代码行,否则将忽略他们
在紧跟在 if 语句后面的代码块中,可根据需要包含任意数量的代码行。
4.3.2 IF-ELSE 语句
if conditional_test:
do something
else:
do something
经常需要在条件测试通过了时执行一个操作,并在没有通过时执行另一个操作;在这种情况下,可使用 Python 提供 IF-ELSE 语句。IF-ELSE 语句块类似于简单的 IF 语句,但其中的 ELSE 语句让你能够制定条件测试未通过时要执行的操作
4.3.3 IF-ELIF-ELSE 结构
if conditional_test1:
do something
elif conditional_test2:
do something
else:
do something
经常需要检查超过两个的情形,为此可使用 Python 提供的 IF-ELIF-ELSE 结构。Python 只执行 IF-ELIF-ELSE 结构中的一个代码块,它一次检查每个条件测试,知道遇到通过了条件测试。通过测试后,Python 将执行紧跟在它后面的代码,并跳过余下的测试。
4.3.4 使用多个 ELIF 代码块
if conditional_test1:
do something
elif conditional_test2:
do something
elif ...:
else:
do something
可根据需要使用任意数量的 ELIF 代码块
4.3.5 省略 ELSE 代码块
Python 并不要求 IF-ELIF 结构后面必须有 ELSE 代码块。在有些情况下,ELSE 代码块很有用,而在其他一些情况下,使用一条 ELIF 语句来处理特定的情形更清晰。
ELSE 是一条包罗万象的语句,只要不满足任何 IF 或 ELIF 中的条件测试,其中的代码就会执行,这可能会引入无效甚至恶意的数据。如果知道最终要测试的条件,应考虑使用一个 ELIF 代码块中来代替 ELSE 代码块。这样你就可以肯定,晋档满足相应的条件时,你的代码才会执行。
4.3.6 测试多个条件
IF-ELIF-ELSE 结构功能强大,但仅适合用于只有一个条件满足的情况;遇到通过了的测试后,Python 就跳过余下的测试。这种行为很好,效率很高,让你能够测试一个特定的条件。
然而,有时候必须检查你关心的所有条件。在这种情况下,应使用一系列不包含 ELIF 和 ELSE 代码块的简单 IF 语句,在可能有多个条件为 True,且你需要在每个添加为 True时都采取相应措施时,适合适用这种方法。
4.4 适用 IF 语句处理列表
通过结合适用 IF 语句和列表,可完成一些有趣的任务;对列表中特定的值做特殊处理;高效地管理不断变化的情形。
4.4.1 检查特殊元素
vegetables = ['aaa', 'bbb', 'ccc', 'ddd']
for vegetable in vegetables:
if vegetable == 'bbb':
print("sorry, " + vegetable.title() + " insufficient inventory.")
else
print(vegetable.title() + " checkout success.")
4.4.2 确定列表不是空的
vegetables = ['aaa', 'bbb', 'ccc', 'ddd']
if vegetables:
for vegetable in vegetables:
if vegetable == 'bbb':
print("sorry, " + vegetable.title() + " insufficient inventory.")
else:
print(vegetable.title() + " checkout success.")
else:
print("It`s closed today.")
4.4.3 使用多个列表
aas = ['aaa', 'bbb', 'ccc', 'ddd']
bbs = ['ccc', 'fff', 'ggg']
for aa in aas:
if aa in bbs:
print("contain.")
else:
print("not cotain.")
4.5 设置 IF 语句的格式
在条件测试的格式设置方面,PEP8 提供的唯一建议是,在诸如==,>=,<=等比较运算符两边各添加一个空格。这样的空格不会影响 Python 对代码的解读,而只是让代码阅读起来更容易。
4.6 小结
在本章中,你学习了如何编写结果要么为 true 要么为 false 的条件测试。你学习了如何编写简单的 IF 语句,IF-ELSE 语句,IF-ELIF-ELSE 结构。在程序中,你使用了这些结构来测试特定的条件,以确定这些条件是否满足。你学习了如何在利用高效的 for 循环的同时,以不同于其他元素的方式对特定的列表元素进行处理,你还再次学习了 Python 就代码格式方面提出的建议,这可确保即便你编写的程序越来越复杂,其代码依然易于阅读和理解。