人工智能基础教程:Python篇(青少版)
上QQ阅读APP看书,第一时间看更新

3.2 循环控制语句

本节将详细介绍Python中的while循环语句和for循环语句以及一些控制语法。

3.2.1 理解Python中的循环语句

Python提供了while循环语句和for循环语句以及break、continue等循环控制语句,循环语句执行的一般流程如图3.5所示。

图3.5 循环语句流程图

循环语句允许执行一条语句或语句组多次,允许更复杂的执行路径。下面来学习本章最重要的两个语句:while循环语句和for循环语句。

3.2.2 while循环语句

具体语法:

while循环语句中的suite_to_repeat会一直循环执行,直到表达式(expression)的值为假(False)。执行流程图如图3.6所示。

图3.6 while循环语句流程图

接下来用一个日常的例子来更加明了地展示while的用法:假如老师让你完成全班同学的成绩评定(全班同学的排列是有序的),你该怎么做呢?在这种情况下,需要为全班的每一个同学都重复执行一次评定代码,也就是在循环中执行评定代码。因为已经将全班同学的排列设置为有序的,这使得我们不用考虑班级成员的姓名,直接用数字代替。具体程序如程序3.4所示。

程序3.4 全体成绩评定:

输出:

分析:

程序的第5~15行是循环执行部分,从缩进格式可以看出它们是在while循环中的,注意最后一行的 count += 1,这是count = count + 1的简写。我们设定count让它在每次的循环之后加1,以此达到控制程序的目的。直到count自增到不再小于num的时候循环结束,也就是说,当count与num相等时不会进入循环结构中,因为这个特性而且我们还要保证循环的次数,所以将count的初值设为0,循环条件设置为count<num,但这样又与编号差1,所以在打印时我们使用count+1(也可以让count初值为1,循环条件为count<=num,这样在打印的时候用count即可)。

注意:

(1)在循环中使用自增变量(就是程序3.4中的变量count)控制循环条件是一种很常见的用法。

(2)对于while循环的循环控制变量要小心对待,因为有些值永远不会为False,这样的循环是永远不会结束的,当然这也不一定是坏事,这取决于实际情况。

通过上面的例子,while语句的用法已经明确了,接下来我们用一个等差数列的例子进一步讨论while的用法。这是一个简单输出指定项数的等差数列(首项为2/3,公差为2/5)各项的程序,具体的各项为2/3、16/15、22/15、28/15(这里只列举数列的前4项)。我们将在这个例子中引入Python中分数的表达方法,这样在本例之外可以使用Python做更多的事情。关于程序的具体解析在分析中有更详细的说明。具体程序如程序3.5所示。

程序3.5 输出指定项数的等差数列的各项:

输出:

分析:

在程序3.5中,我们使用Python提供的Fraction方法来表示分数,它的原型是:

也就是说,它接收两个参数,第一个作为分子,第二个作为分母。它可以直接与数运算(如Fraction(5,16)+3),也可以在Fraction对象之间相互运算〔如Fraction(1, 16)* Fraction(3,16)〕。另外,关于模块、对象的详细使用方法后文会介绍,在这里你可以简单地将Fraction(2, 3)理解为我们平时笔算时写的2/3。

现在继续回到程序中,第1行中的语句可以简单地理解为将Fraction模块导入到此程序中,这样就能用Fraction方法了。接下来我们使用step表示公差,在while循环中不断地加到首项上,以此构造一个等差数列,并在最后输出。while循环还是和上一个例子一样,是通过自增变量控制的。程序流程图如图3.7所示。

图3.7 程序流程图

思考题:

Fibonacci数列是数学中一个非常重要的数列,它指数列前两项为1并且从第3项开始往后,每一项都等于前两项之和。例如,数列的前5项为“1, 1, 2, 3, 5”。在这里我们来思考一下,如何使用while循环语句输出最后一项小于1000Fibonacci数列。

关于Fibonacci数列还有一种递归实现,关于递归的概念以及具体实现方式在本书的函数部分会详细讲解。

3.2.3 for循环语句

具体语法:

for循环是Python提供的另一个循环机制,它会依次访问一个已选定的可迭代对象(例如,我们很常见的字符串、序列或是元组)中的所用元素,即遍历可迭代对象,这个过程在具体语法中就是将iter_var设置为iterable中的当前元素,当iterable中的所有的条目(如序列中的项)都处理过后结束循环。执行流程如图3.8所示。

图3.8 for循环语句流程图

注意:

读完上面这一段for循环的具体介绍,你可能会有疑问,什么是迭代?你可以将迭代理解为一种环形结构,它也叫循环,while和for语句也被称为迭代语句。

如果你之前接触过C/C++或者Java的话,请一定注意,Python中的for语句与其他编程语言的用法不同。

到这里我们已经知道了for循环会遍历一个可迭代对象,下面来看看如何使用它。我们介绍两种基本方法:使用序列项或者序列索引。假如已经拿到你们小组的名单,而老师需要你将小组成员的名字和组号一同输出。诸如此类的情况,for语句可以很好地实现。

程序3.6会使用序列项迭代来遍历输出名单上的名字。

程序3.6 使用序列项迭代:

输出:

分析:

程序中name是一个列表,代表着小组成员名单,我们用for语句迭代这个列表,其中item变量在每次的循环中都会被赋值为列表中的某个特定的元素,以供循环中的语句使用。

介绍完使用序列项迭代之后,我们来看看另一种方法,使用序列索引迭代。不同于使用序列项迭代,使用序列索引迭代就如同字面意思所说,操作的重点在于拿到序列索引号并通过它获取序列中的项。还是上面的例子,我们改用序列索引迭代实现,具体程序如程序3.7所示。

程序3.7 使用序列索引迭代:

输出:

分析:

本程序和程序3.6看上去相似,但是并不相同,在本程序中你会发现一个略显生疏的函数—range,它的作用是返回一个序列,这个序列正好就是我们需要的迭代序列。我们将range的参数设置为姓名列表(name)的长度,这样从range(len(name))中获取的数即可作为name的索引数(注意使用range函数获取序列的值是从0开始,len(name)-1结束),再使用name列表的切片操作来获取与索引值相对应的项,并在for循环中完成输出。

看完分析你可能仍对range函数存有疑惑,下面我们再详细地谈谈range函数。先来看看完整的range函数:

range函数会返回一个包含所有项的列表,这里我们假设项为i, i会满足start<= i < end,从start开始,i每次递增step(注意:step一定不能为0)。例如,range(2, 6, 2)会返回列表[2, 4]。

我们经常用到的是它的两种简化形式:

第一种只接收一个end值,它的start默认为0,step为1。例如,range(3)会返回列表[0, 1, 2]。第二种接收两个值,它的step默认为1。例如,range(2, 4)会返回列表[2, 3]。

当for循环涉及数字操作的时候,使用range函数是很有用的。

提示:

如果你的程序需要考虑到性能的问题,那么对于上文所讲的序列项迭代和索引迭代,序列项迭代的速度会更快。

注意:

这里,我们已经知道 for 循环会依次访问一个已选定的可迭代对象的所有元素。你是否会疑惑,它是怎样做到的呢?实际上,在 for 循环的内部,它会自动帮我们调用迭代器的next()方法来达到遍历的效果,它也会捕获StopIteration异常使循环结束。这样便可以完成上文所提到的功能。

现在你应该对于for循环有了更深的理解,接下来用一个大家都很熟悉的例子巩固一下。在物理课上你应该做过用打点计时器测速度的实验(人教版高中物理必修1第一章),现在假设我们拿到的纸带如图3.9所示。

图3.9 用于实验的纸带

已知打点计时器所用电源频率为50Hz, AB距离为0.0040m, BC距离为0.0102m, CD距离为0.0106m。我们要求每一段的平均速度。具体程序如程序3.8所示。

程序3.8 求纸带上每段距离的平均速度:

输出:

分析:

本程序涉及物理课中的一个很简单的测速实验,在这里我们假设已经测量完纸带的间距并将它们存储在item_len列表中,用item遍历获取item_len列表中的各段距离值用于for循环中的具体操作。由打点计时器所用的电源频率为50Hz可知,纸带上两点间隔的时间为0.02s,得到这些条件后,用/vxt=DD来求得每段的平均速度。程序流程图如图3.10所示。

图3.10 程序流程图

注意:

在编程的时候,我们可以让两个字符串相加达到组成一个字符串的目的,但是,在程序3.8中的print语句中你不能使用print("{0} m/s" + item/sec)的形式进行输出,因为此时item/sec是float类型,这样做会让你的程序报错:TypeError: must be str, not float。像这种从其他信息中构造字符串正是format()方法大有用武之地的地方。

3.2.4 break语句

break语句在控制中很常见,它可以终止当前的循环,即跳出循环语句执行程序中的下一条语句。执行流程图如图3.11所示。

图3.11 break语句流程图

现在我们已经对break语句有了一定的了解,接下来用一个例子来实践一下。我们都笔算过最大约数,接下来就用Python实现算出最大约数。

程序3.9 求一个数的最大约数:

输出:

分析:

在程序3.9中,因为count的值是不断递减的,所以第一个能整除num的数便是我们要找的,后续的数就没有必要考虑了,使用break语句跳出循环。程序流程图如图3.12所示。

图3.12 程序流程图

3.2.5 continue语句

我们可以将continue语句理解为跳过当前的循环块,继续该循环的下一次迭代。先来看看continue语句的执行流程图,如图3.13所示。

图3.13 continue语句流程图

接下来用一个判定提交的选项是否正确(假设正确的选项为C)的程序来看看continue语句是如何工作的。

程序3.10 判断提交选项:

输出:

分析:

在这个程序中不仅用到了continue语句,还用到了许多之前提到过的语句。在第1行中使用True作为while的循环条件以达到可以不断地对选项进行判断的目的,若输入不是C,那么将使用continue语句跳过本次循环,重复下一次循环,直到输入C并执行break语句,才终止循环并获得Congratulations!。程序流程图如图3.14所示。

图3.14 程序流程图