
3.3 循环结构
循环结构用来重复执行一条或多条语句,使用循环结构可以减少源程序重复书写的工作量。许多算法需要使用到循环结构,Python使用for语句和while语句来实现循环结构。
3.3.1 可迭代对象
可迭代对象(iterable)一次返回一个元素,因此适用于循环。Python()包括以下几种可迭代对象:序列(sequence),例如字符串(str)、列表(list)、元组(tuple)等;字典(dict);文件对象;迭代器对象(iterator);生成器函数(generator)。
迭代器是一个对象,表示可迭代的数据集合,包括方法__iter__()和__next__(),可以实现迭代功能。
生成器是一个函数,使用yield语句,每次产生一个值,也可以用于循环迭代。
3.3.2 range对象
Python 3中的内置对象range是一个迭代器对象,在迭代时产生指定范围的数字序列,其格式如下。

range返回的数字序列从start开始,到stop结束(不包含stop)。如果指定了可选的步长step,则序列按步长step增长。例如:

注意,Python 2中range的类型为函数,是一个生成器;Python 3中range的类型为类,是一个迭代器。
3.3.3 for循环
for语句用于遍历可迭代对象集合中的元素,并对集合中的每个元素执行一次相关的嵌入语句。当集合中的所有元素完成迭代后,控制传递给for之后的下一个语句。for语句的格式如下。

例如:

【例3.9】 利用for循环求1~100中所有奇数的和以及所有偶数的和(for_sum1_100.py)。

程序运行结果如下。

3.3.4 while循环
与for循环一样,while也是一个预测试的循环,但是while在循环开始前并不知道重复执行循环语句序列的次数。while语句按不同条件执行循环语句(块)零次或多次。while循环语句的格式如下。


图3-4 while循环的执行流程
while循环的执行流程如图3-4所示。
说明:
(1)while循环语句的执行过程如下。
①计算条件表达式。
②如果条件表达式的结果为True,控制将转到循环语句(块),即进入循环体。当到达循环语句序列的结束点时转①,即控制转到while语句的开始,继续循环。
③如果条件表达式的结果为False,退出while循环,即控制转到while循环语句的后继语句。
(2)条件表达式是每次进入循环之前进行判断的条件,可以为关系表达式或逻辑表达式,其运算结果为True(真)或False(假)。在条件表达式中必须包含控制循环的变量。
(3)循环语句序列可以是一条语句,也可以是多条语句。
(4)在循环语句序列中至少应包含改变循环条件的语句,以使循环趋于结束,避免“死循环”。
【例3.10】 利用while循环求,以及1~100中所有奇数的和、所有偶数的和(while_sum.py)。

程序运行结果如下。

【例3.11】 用以下近似公式求自然对数的底数e的值,直到最后一项的绝对值小于10-6为止(while_e.py)。


程序运行结果如下。

3.3.5 循环的嵌套
若在一个循环体内又包含另一个完整的循环结构,则称之为循环的嵌套。这种语句结构称为多重循环结构。在内层循环中还可以包含新的循环,以形成多层循环结构。
在多层循环结构中两种循环语句(for循环、while循环)可以相互嵌套。多重循环的循环次数等于每一重循环次数的乘积。
【例3.12】 利用嵌套循环打印运行效果如图3-5所示的九九乘法表(nest_for.py)。

图3-5 九九乘法表的运行效果图

思考:请修改程序,分别打印如图3-6(a)和图3-6(b)所示的九九乘法表。

图3-6 九九乘法表的另外两种显示效果
3.3.6 break语句
break语句用于退出for、while循环,即提前结束循环,接着执行循环语句的后继语句。注意,当多个for、while语句彼此嵌套时,break语句只应用于最里层的语句,即break语句只能跳出最近的一层循环。
【例3.13】 使用break语句中止循环(break.py)。

程序运行结果如下。

【例3.14】 编程判断所输入的任意一个正整数是否为素数(prime1.py和prime2.py)。
所谓素数(或称质数),是指除了1和该数本身之外不能被任何整数整除的正整数。判断一个正整数m是否为素数,只要判断m可否被中的任何一个整数整除即可,如果m不能被此范围中的任何一个整数整除,m即为素数,否则m为合数。
方法一(利用for循环和break语句):

方法二(利用while循环和bool变量):

3.3.7 continue语句
continue语句类似于break语句,也必须在for、while循环中使用,但它结束本次循环,即跳过循环体内continue下面尚未执行的语句,返回到循环的起始处,并根据循环条件判断是否执行下一次循环。
continue语句和break语句的区别在于:continue语句仅结束本次循环,并返回到循环的起始处,如果循环条件满足就开始执行下一次循环;而break语句则是结束循环,跳转到循环的后继语句执行。
与break语句类似,当多个for、while语句彼此嵌套时continue语句只应用于最里层的语句。
【例3.15】 使用continue语句跳过循环示例(continue_score.py)。要求输入若干学生成绩(按Q或q键结束),如果成绩<0,则重新输入。统计学生人数和平均成绩。

程序运行结果如下。

【例3.16】 显示100~200不能被3整除的数(continue_div3.py)。要求一行显示10个数。程序运行结果如图3-7所示。

图3-7 显示100~200不能被3整除的数

3.3.8 死循环
如果while循环结构中的循环控制条件一直为真,则循环将无限继续,程序将一直运行下去,从而形成死循环。
当程序死循环时会造成程序没有任何响应,或者造成不断输出(例如控制台输出、文件写入、打印输出等)。
在程序的循环体中,插入调试输出语句,可以判断程序是否为死循环。注意,有的程序算法十分复杂,可能需要运行很长时间,但并不是死循环。
在大多数计算机系统中,可以使用Ctrl+C组合键中止当前程序的运行。
【例3.17】 死循环示例(infinite.py)。

本程序因为循环条件为“while True”,所以将一直重复提示用户输入一个正数,计算并输出该数的平方根,从而形成死循环。所以,最后的“print("Good bye!")”语句将没有机会执行。
3.3.9 else子句
for、while语句可以附带一个else子句(可选)。如果for、while语句没有被break语句中止,则会执行else子句,否则不执行。其语法如下。

或者:

【例3.18】 使用for语句的else子句(for_else.py)。

程序运行结果如下。

3.3.10 enumerate()函数和循环
Python语言的for循环直接迭代对象集合中的元素,如果需要在循环中使用索引下标访问集合元素,则可以使用内置的enumerate()函数。
enumerate()函数用于将一个可遍历的数据对象(例如列表、元组或字符串)组合为一个索引序列,并返回一个可迭代对象,故在for循环当中可直接迭代下标和元素。
【例3.19】 enumerate()函数和下标元素循环示例(enumerate.py)。

程序运行结果如下。

3.3.11 zip()函数和循环
如果需要并行遍历多个可迭代对象,则可以使用Python的内置函数zip()。
zip()函数将多个可迭代对象中对应的元素打包成一个个元组,然后返回一个可迭代对象。如果元素的个数不一致,则返回列表的长度与最短的对象相同。
利用运算符*还可以实现将元组解压为列表。例如:

【例3.20】 zip()函数和并行循环示例(zip.py)。

程序运行结果如下。

3.3.12 map()函数和循环
如果需要遍历可迭代对象,并使用指定函数处理对应的元素,则可以使用Python的内置函数map()。
map(func,seq1[,seq2,…])函数将func作用于seq中的每一个元素,并将所有的调用结果作为可迭代对象返回。如果func为None,该函数的作用等同于zip()函数。
例如,如果要返回列表中每个字符串的长度,可以使用内置的map()函数和len()函数:

【例3.21】 map()函数和循环示例。

3.3.13 循环语句的典型示例代码
使用for语句和while语句都能实现循环功能,选择哪种语法构造取决于程序员的偏好。循环语句的典型示例如表3-2所示。
表3-2 for语句和while语句的典型示例

3.3.14 循环结构综合举例
【例3.22】 使用牛顿迭代法求解平方根(sqrt.py)。其运行效果如图3-8所示。
计算一个正实数a的平方根可以使用牛顿迭代法实现:首先假设t=a,开始循环,如果t=a/t(或小于容差),则t等于a的平方根,循环结束并返回结果;否则将t和a/t的平均值赋给t,继续循环。

【例3.23】 显示Fibonacci数列(for_fibonacci.py):1、1、2、3、5、8……的前20项。即

要求每行显示4项。其运行效果如图3-9所示。

图3-8 使用牛顿迭代法求解平方根

图3-9 显示Fibonacci数列
相关语句如下:
