
2.3 循环结构
循环结构是控制一个语句块重复执行的程序结构,它由循环体和循环条件两部分组成,其中循环体是重复执行的语句块,循环条件则是控制是否继续执行该语句块的表达式。循环结构的特点是在一定条件下重复执行某些语句,直至重复到一定次数或该条件不再成立为止。
在Python语言中,可以通过while语句和for语句来实现循环结构,也可以通过break语句、continue语句以及pass语句对循环结构的执行过程进行控制,此外还可以在一个循环结构中使用另一个循环结构,从而形成循环结构的嵌套。
2.3.1 while语句
while语句的功能是在满足指定条件时执行一个语句块,其一般语法格式如下:
while 表达式:
语句块
其中表达式表示循环条件,它通常是关系表达式或逻辑表达式,也可以是结果能够转换为布尔值的任何表达式;表达式后面必须添加冒号。语句块是重复执行的单个或多个语句,称为循环体。当循环体只包含单个语句时,也可以将该语句与while写在同一行;当循环体包含多个语句时,这些语句必须向右缩进,而且具有相同的缩进量。
while语句的执行流程如下:首先计算表达式的值,如果该值为True,则重复执行循环体中的语句块,直至表达式的值变为False才结束循环,接着执行while语句的后续语句。整个执行流程如图2-4所示。
注意:在while语句中,如果条件表达式的值恒为True,则循环将无限地执行下去,这种情况称为死循环。为了避免出现死循环,必须在循环体内包含能修改条件表达式值的语句,使该值在某个时刻变为False,从而结束循环。

图2-4 while语句的执行流程
在Python中,允许在循环语句中使用可选的else子句,即:
while 表达式:
语句块1
else:
语句块2
其中语句块2可以包含单个或多个语句,这些语句将在循环正常结束的情况下执行。如果是通过break语句中断循环,则不会执行语句块2中的语句。
【例2.10】 国际象棋棋盘由64个黑白相间的格子组成。假如在第1个格子里放1颗麦粒,在第2个格子里放2颗麦粒,在第3个格子里放4颗麦粒,以后每个格子里放的麦粒数都比前一个格子增加一倍,请问在第64个格子里放的麦粒数是多少?这样摆满棋盘上的64个格子一共需要多少颗麦粒?
【算法分析】
棋盘格子序号用变量i表示,i的取值范围为0~63,0表示第1个格子,1表示第2个格子,以此类推;序号为i的格子里放的麦粒数为n=2**i;麦粒数用变量sum表示。摆满棋盘后所有格子里的麦粒数可以使用while语句进行计算。循环条件为i<=63,在循环体中将每个格子里的麦粒数累加起来并存入变量sum,并使变量i增加1。待循环正常结束后用print()函数输出结果即可。
【程序代码】

【运行结果】
第64个格子里放的麦粒数为9223372036854775808。
摆满棋盘时所有格子里的麦粒数为18446744073709551615。
2.3.2 for语句
在Python中,for语句是一个通用的序列迭代器,可以用于遍历(是指沿着某条搜索路线,依次对序列中每个对象均做一次且仅做一次访问)任何有序序列对象中的所有元素,其一般语法格式如下:
for 循环变量 in 序列对象:
语句块
其中循环变量不需要事先进行初始化。序列对象指定要遍历的字符串、列表、元组、集合或字典。语句块表示循环体,可以包含单个或多个语句。当循环体只包含单个语句时,也可以将这个语句与for写在同一行;当循环体包含多个语句时,这些语句必须向右缩进,而且必须具有相同的缩进量。
for语句的执行流程如下:将序列对象中包含的元素依次赋给循环变量,并针对当前元素执行一次循环体语句块,直至序列中的每个元素都已用过,遍历结束为止。整个执行流程如图2-5所示。
与while语句一样,在for语句中也可以使用一个可选的else子句。当for循环正常结束时将会执行else子句。如果是通过执行break子句而中断for循环,则不会执行else子句。
【例2.11】 4个人中有一个人打碎了花瓶,A说不是我,B说是C,C说是D,D说C撒谎,已知有3个人说了真话,根据以上对话判断是谁打碎了花瓶。

图2-5 for语句的执行流程
【算法分析】
打碎花瓶的人必是4个人中的一个,可将这些人的编号存入字符串中,并使用for循环语句来遍历所有编号,对每个人的说法进行判断,如果某人说的是真话,则关系表达式的值为True,可以转换为整数1。在循环体中,用if语句判断是否满足“三人说真话”的条件,如果满足,则输出结果。
【程序代码】

【运行结果】
答案:是C打碎了花瓶。
如果需要遍历一个整数序列,则可以使用range()函数来创建该序列,调用格式如下:
range([start,]end[,step])
其中参数start为可选项,用于指定序列的起始值,默认值为0;参数end用于指定序列的结束值,这是一个半开区间,不包括end本身的值;参数step为可选项,用于指定序列的步长,默认值为1。
例如,下面的语句用于遍历整数序列0~9:

【例2.12】 从键盘输入一个自然数,判断它是不是素数。
【算法分析】
根据数学知识可以知道,素数是一个大于1的自然数,其特点是除了1和它自身之外不能被其他自然数整除。要判断一个自然数n是不是素数,可以使用2,4,…,去除它,如果都不能整除,则n为素数。对于输入的自然数n,可以使用range()函数生成整数序列2,4,…,
+1,并通过for循环语句遍历这些整数,依次判断每个数能否整除n。如果n不等于1且能被序列中的某个整数整除,则n不是素数。
【程序代码】


【运行结果】

再次运行程序:

2.3.3 循环控制语句
循环语句的正常执行流程是在满足循环条件时执行循环体,一旦循环条件不再满足便会执行else子句或者继续执行循环语句的后续语句。如果需要改变循环的执行流程,可以使用Python提供的以下3个循环控制语句。
1.break语句
break语句用来终止当前循环的执行操作,其语法格式如下:
break
break语句用在while和for循环中,通常与if语句一起使用,可以用来跳出当前所在的循环结构,即使循环条件表达式的值没有变成False或者序列还没被完全遍历完,系统也会立即停止执行循环语句,即跳出循环体,跨过else子句(如果有的话),转而执行循环语句的后续语句。
【例2.13】 计算前100个自然数之和。
【算法分析】
一般情况下,while循环会在循环条件变为False时正常结束。如果循环条件恒为True,则会形成死循环。如果在这种死循环中添加break语句,并在满足一定条件时执行break语句,则可以跳出循环结构,由此形成半路循环,这种结构在编程中经常用到。为了展示break语句的应用,本例中的计算任务将通过这种半路循环来完成。
【程序代码】

【运行结果】
1+2+...+100=5050
2.continue语句
continue语句用于跳出本次循环,其语法格式如下:
continue
与break语句一样,continue语句也是用在while和for循环中,通常也是与if语句一起使用,但两者的作用有所不同。continue语句用来跳过当前循环的剩余语句,然后继续进行下一轮循环;break语句则是用于跳出整个循环,然后继续执行循环语句的后续语句。
【例2.14】 展示continue语句与break语句的区别示例。
【程序代码】

【运行结果】

3.pass语句
为了保持程序结构的完整性,Python提供了一个空语句pass。pass语句一般仅作为占位语句,不做任何事情,其语法格式如下:
Pass
【例2.15】 展示pass语句的应用示例。
【程序代码】

【运行结果】
当前字母:P
当前字母:y
当前字母:t
在这里遇到了pass语句。
当前字母:h
当前字母:o
当前字母:n
再见!
2.3.4 循环结构的嵌套
在一个循环结构中可以嵌入另一个循环结构,由此形成嵌套的循环结构,也称为多重循环结构,例如二重循环和三重循环。多重循环结构由外层循环和内层循环组成,当外层循环进入下一轮循环时,内层循环将重新初始化并开始执行。如果在多重循环结构中使用break语句和continue语句,则这些语句仅作用于其所在层的循环。
使用多重循环结构时,嵌套的深度不限,但是需要特别注意代码的缩进问题,内层循环与外层循环之间不能交叉。
【例2.16】 输出乘法口诀表。
【算法分析】
输出乘法口诀表可以通过一个二重循环来实现,外层循环需要执行9次,每执行一次输出一行;各外层循环输出的结果位于不同的行。内层循环执行的次数由行号决定,行号是多少内层循环就执行多少次,每执行一次输出一个等式;同一个内层循环输出的所有等式位于同一行。
【程序代码】

【运行结果】
乘法口诀表
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
1×4=4 2×4=8 3×4=12 4×4=16
1×5=5 2×5=10 3×5=15 4×5=20 5×5=25
1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36
1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49
1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64
1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81