第4章 if语句与循环语句

4.1 问题:Python控制语句有何特点?

在Python中,可以把循环语句、if语句放在一行里,而这就是Python控制语句的特点之一。把if与循环语句组合在一起,既增量了Python代码的可读性,也使Python代码更加简洁、高效。例如,选出列表lst7=[98,97,87,88,76,68,80,100,65,87,84,92,95,87]中大于90的元素,Python只要一句即可完成。

由此,可见Python语言的简洁和高效。Python的控制语句可以有机组合在一行,Python的控制语句还可与表达式写在一行,如下语句:

类似的特点还有很多,后续章节我们会经常看到。

4.2 if语句

在实际生活中,我们经常遇到分类统计的情况。对不同分类或不同状态,做不同处理,如果用程序实现的话,可以用if语句来实现。

4.2.1 if语句格式

if语句用于检测某个条件是否满足。满足,执行一个逻辑块;不满足则执行另一个逻辑块。if语句的一般格式为:
if 条件 :
代码块1
else:
代码块2
Rrrr
这是只有两种情况,如果情况更多,可以使用更多分支的if语句,如下代码样例。
if 条件1 :
elif 条件2 :
else:
代码块3
if语句以关键字if开头,然后跟一个布尔表达式或if条件,if条件后面是一个冒号(:),代码块1、代码块2等都缩进4格,以相同缩进作为代码块的标志,同级代码块必须用相同的缩进格数。多一个或少一个都会报错,这条规则必须严格遵守。Python将冒号:作为if、循环语句、函数定义一行的结束标记。

4.2.2 if语句

给出一个年龄值,利用if-elif-else结构,判断该年龄值属于哪个年龄段。以下是实现代码。

4.2.3 使用and连接条件语句

根据给定年龄,判断属于哪个年龄段的问题,if的条件也可用and连接。

4.2.4 元素是否在列表中

如果要判断一个元素是否在一个列表或元组中,可以使用in或not in 的方法。当列表非常大时,这种方法效率非常高。例如,判断"keras"是否在列表lst42=["Pythoon","Numpy","Matplotlib","OpenCV","Sklearn","Pytorch","Keras","TensorFlow"],假设列表lst42表示目前环境已安装的软件。我们用if语句中带not的条件即可,具体实现如下:

结果:keras不在列表中
这个结果乍一看,与我们的期望不一样,keras应该在lst42中,不过仔细再看一下,问题在大小上,lst42中是"Keras",第一个字母是大写,而我们使用的keras为小写。为此,我们可以把lst42的字符全变成小写,然后再进行比较,修改后的代码如下;

结果:keras在列表中

4.2.5 缩进易出现的问题

Python是通过缩进来判断是否属于一个代码块,而不是通过显式的{}或[]等来说明。所以出现缩进问题不易发现,与缩进有关还一个冒号,在Python中冒号往往表示Python一个语句的结束,一个逻辑块的开始(这句话不一定很准确)。我们先看一些易疏忽的问题。
(1)忘记缩进

这个if语句将报错,因 if a (2)忘记加上冒号

这个语句将会在else报错,因else后没有冒号。
(3)有缩进,但缩进的格数不同

这个if语句也会报错,因这两个print语句属于同一级的逻辑块,但缩进的格数不一致。
为尽量避免类似问题,大家编写代码时,尽量使用一些工具,如PyCharm,或Jupyter等,使用这些工具,遇到冒号回车将自动缩进,而且报错后,出错的地方会高亮或被标注。

4.3 循环语句

循环语句用来重复执行一些代码块,通常用来遍历序列、字符串、字典、迭代器等,然后对其中每个元素做相同或类似处理,字典、迭代器后续将介绍。Python有两种循环:for循环和while循环。for循环通常用于已知对象,while循环基于某个条件,满足这个条件循环执行,否则结束循环。

4.3.1 for循环

我们先看for循环的一个简单实例,从range(10)中每次读取一个数,然后打印这个数。

for循环的关键字为for,接下来是循环变量(这里为i,当然也可是其它变量),然后是关键字in,关键字in后是序列、字符串、字典等可迭代对象,最后以冒号结束。每次循环结束时,循环变量就被设置成下一个值,直到获取最后一个值为止。
for循环与if语句一起使用,可以产生各种各样的数据,比如,利用for循环及if语句可以统计列表lst41=["a","b","a","a","b"]中的a和b各出现多少次。
列表lst41的分类统计,用代码实现如下:

4.3.2 while 循环

while循环的执行过程:首先检查循环条件为True或False,如果为True,就执行循环体;如果为False,就跳出循环,执行后面的语句。我们用while循环实现上节for循环的内容。

使用while循环时,要避免出现死循环问题,如果这个while 循环少了i=i+1这个条件,,那么这个循环将一直执行下去,除非强制结束循环或按ctrl+c停止执行当前任务。

4.3.3 嵌套循环

Python中for循环和while循环都可以进行循环嵌套,for循环中又有for循环或while循环;while循环中有while循环或for循环。
这里我们看一个for循环中又有for循环的情况。比如要累加列表lst42=[[1,2,3],[4,5,6],[7,8,9]]中这9个数据,可以先用一个for循环里面的每个列表,然后,再用一个for循环累加取出的每个列表的元素。具体实现如下;

循环是很耗资源的,实现编程中要尽量避免使用循环,尤其是循环嵌套,因循环嵌套可读性较差,更重要的是耗资源又慢。后续我们将介绍不使用循环,直接利用矩阵进行计算,其性能是使用循环的几倍甚至几十、几百倍。

4.3.4 break跳出循环

在for循环、while循环都可以使用break跳出整个循环,不再执行剩下的循环语句。如果break在循环嵌套里,break将跳出所在或当前循环。
比如,在一个列表中,查找一个单词,如果没有找到继续查询,一旦找到,就停止查找,退出循环。

结果:
找了3次,终于找到了!
总的查询次数:3次
从总的查询次数是3次,可以看出,一旦找到就停止循环,不再查找了。

4.3.5 continue加快循环

与break跳出循环不同,continue不是立即跳出整个循环,而是立即返回循环开头,继续循环,直到循环结束。
上面这个查找例子,如果把break,换成continue,会是什么情况呢?

结果:
找了3次,终于找到了!
总的查询次数:6次
说明找到白骨精后,循环还继续,直到找遍列表中所有元素为止。
break结束循环,continue继续循环,这就是两种最大的区别。

4.3.6 列表推导式

这节主要介绍列表推导式,列表推导式提供了一种简单明了的方法来创建列表。
它的结构是在一个中括号里包含一个表达式,然后是一个for语句,后面再接0个或多个for或者if语句。那个表达式可以是任意的,意味着你可以在列表中放入任意类型的对象。返回结果将是一个新的列表。以下通过实例来说明。
假设我们要把从1到100这100个自然数中的偶数取出来,为实现这个需求,我们采用两种方法,一种是普通方法,另一种是采用列表推导式,然后,比较两种方法。
(1)使用普通方法
使用普通方法就是先创建一个空列表,执行一个循环语句,在循环语句里加上if语句,判断是否为偶数,是偶数则追加到这个列表中。

(2)使用列表推导式
使用列表推导式,就是把for循环和if语句在一行来完成整个逻辑,具体代码如下:

一句话就搞定了,简洁明了,还高效!

4.4 练习

(1)求1到100连续自然数中偶数的和
(2)列表[2,4,-1,0,10,0,-2,9]按升序排序。
(3)编写一个脚本,对任意一个列表进行升序排序
(4)过滤第(2)题的列表中小于等于0的值。
(5)假设x=[1,2,3],y=[4,5,6],求两点x,y之间的距离。

(6)编写一个程序,统计从1到99共有多少个6字。