第3 章 Python 控制语句 学习目标 .理解结构化程序设计的3种基本结构。 .掌握分支结构if语句的用法。 .掌握for循环结构。 .掌握while循环结构。 3.1 结构化程序设计 3.1 程序流程图 1. 程序流程图是用统一规定的标准符号描述程序运行具体步骤的图形,通过对输入输 出数据和处理过程的详细分析,将计算机的主要运行步骤和内容标识出来,是进行程序设 计的最基本依据。 程序流程图由起止框、判断框、处理框、输入输出框、连接点、流程线、注释框等元素构 成,如图3. 1所示。 图3. 1 程序流程图的构成元素 第3章 Python控制语句53 其中,起止框表示程序的开始或结束;判断框(菱形框)具有条件判断功能,有一个入 口,两个出口;处理框具有处理功能;输入输出框表示数据的输入或程序结果的输出;连接 点可将流程线连接起来;流程线表示流程的路径和方向;注释框是为了对流程图中某些框 的操作进行必要的补充说明。图3. 2为流程图示例。 图3. 2 程序流程图示例 3.2 程序的基本结构 1. 结构化程序设计方法的基本思想是以系统的逻辑功能设计和数据流关系为基础,根 据数据流程图和数据字典,借助标准的设计准则和图表工具,通过“自上而下”和“自下而 上”的反复,逐层把系统划分为多个大小适当、功能明确、具有一定独立性并容易实现的模 块,从而把复杂系统的设计转变为多个简单模块的设计。结构化程序设计方法可以用3 个关键词进行概括;自上而下、逐步求精、模块化设计。 结构化的含义指用一组标准的准则和工具从事某项工作。在结构化程序设计之前, 每一个程序员都按照各自的习惯和思路编写程序,没有统一的标准,也没有统一的技术方 法,因此,程序的调试、维护都很困难,这是造成软件危机的主要原因之一。20 世纪60 年 代,计算机科学家提出了有关程序设计的新理论,即结构化程序设计理论。该理论认为, 任何一个程序都只需用3种基本逻辑结构来编制,分别是顺序结构、分支结构(选择结构) 和循环结构。这种程序设计的新理论促使人们采用模块化编制程序,把一个程序分成若 干个功能模块,这些模块之间尽量彼此独立,再用控制语句或过程调用语句将这些模块连 接起来,形成一个完整的程序。一般来说,结构化程序设计方法不仅大大改进了程序的质 量和程序员的工作效率,而且还增强了程序的可读性和可维护性。 结构化程序的结构可以用很多种方式表示,例如程序流程图、N-S图、PAD 图等。程 序流程图是广泛使用的结构化设计表示工具,具有表达直观,易于掌握的特点。 54Python学习从入门到实践(第2版) 1.顺序结构 顺序结构指程序从第一行语句开始执行,执行到最后一行语 句结束,程序中的每条语句都会被执行一次。顺序结构的程序流 程图如图3. 3所示。 2.分支结构图3. 3 顺序结构的 分支结构也称选择结构,表示程序的处理步骤出现了分支,它 程序流程图 需要根据某一特定的条件选择其中的一个分支执行。分支结构分为单分支结构、双分支 结构和多分支结构。 (1)单分支结构:当判断条件为真值时,执行语句块1;当判断条件为假值时,越过语 句块往下执行其他语句或结束,通常用来指定某一段语句是否执行。单分支结构的程序 流程图如图3. 4所示。 (2)双分支结构:当判断条件为真值时,执行语句块1;当判断条件为假值时,执行语 句块2,通常用来有选择地在两段语句中选择一段执行。双分支结构的程序流程图如 图3. 5所示。 图3.4 单分支结构的程序流程图图3. 5 双分支结构的程序流程图 (3)多分支结构:即扩展的双分支结构, n 或者n+1 个语句块, 一般设有 n 个条件, 当判断条件从上往下判断到某个条件为真值时执行对应的语句块,然后退出多分支结构 继续向下执行其他内容。需要注意的是,多分支结构在一次执行时只能选择一个分支,即 使其他判断条件为真值,也不会继续判断执行。多分支结构的程序流程图如图3. 6所示。 3. 循环结构 循环结构是程序根据条件判断,在满足条件的情况下反复执行某个语句块的运行方 式。根据循环触发条件的不同,分为条件循环和遍历循环。条件循环结构在执行循环时 先判断循环条件的取值,如果为True则执行一次语句块(循环体), 然后返回继续判断循 第3 章 Python 控制语句 55 图3.6 多分支结构的程序流程图 环条件,如果循环条件为False,则结束循环。条件循环程序流程图如图3.7所示。遍历 循环在执行循环时也要进行判断,看循环变量是否在遍历队列中,如果在,则取一个遍历 元素,执行一次语句块(循环体),然后返回再取下一个遍历元素,直到遍历元素取完,循环 结束。遍历循环的程序流程图如图3.8所示。 图3.7 条件循环结构的程序流程图 图3.8 遍历循环结构的程序流程图 3.2 分支结构 3.2.1 单分支结构 Python中单分支if语句的语法格式如下: if <条件>: <语句块> 56 Python 学习从入门到实践(第2 版) 条件是一个表达式,其结果一般为真值True或者假值False。语句块是if条件满足 后执行一条或多条语句的序列。程序执行到if语句时,如果判断条件为True,则执行语 句块;条件为False,则跳过语句块。无论条件为True还是False,单分支执行结束后都会 执行与if语句同级别的下一条语句继续执行程序。 分支结构中的条件在多数情况下是一个关系比较运算。形成比较的最常见方式是利 用关系操作符。Python语言共有6个关系操作符,如表2.2所示。 【例3.1】 输入两个数字,输出其中较大数字。 程序代码如下。 #example3.1 x = eval(input("请输入第一个数字:")) y = eval(input("请输入第二个数字:")) print("输入的两个数字为:",x,y) if x>y: print("较大的是:",x) if x>> ================RESTART:C:/Python/python36/example3.1.py================ 请输入第一个数字:8 请输入第二个数字:15 输入的两个数字为:8 15 较大的是: 15 >>> 说明如下。 (1)可以用input()函数输入两个数字,然后对它们进行判断比较,如果某个数字比 较大,就用print()函数输出该数字。 (2)运行后,程序对输入的两个数字进行判断,例如当输入的两个数字为8和15时, 执行第一个if语句,判断条件x>y为假值False,不执行print("较大的是:",x)语句,分 支判断结束;执行第二个if语句,判断条件x: <语句块1> else: <语句块2> 双分支结构根据条件的真假值来有选择地执行语句块1或语句块2。当条件为True 时,执行语句块1,然后结束分支结构;当条件为False时,执行语句块2,然后结束分支 结构。 【例3.2】 用双分支结构改写例3.1。 程序代码如下: #example3.2 x= eval(input("请输入第一个数字:")) y= eval(input("请输入第二个数字:")) print("输入的两个数字为:",x,y) if x>y: print("较大的是:",x) else: print("较大的是:",y) 程序运行结果如下(输入顺序为10和5): >>> ========= RESTART: C:/ Python/Python36/example3.2.py ========= 请输入第一个数字:10 请输入第二个数字:5 输入的两个数字为:10 5 较大的是: 10 >>> 说明如下。 (1)如果不考虑两个数字相等的情况,可以将例3.1中两个单分支if结构合并为一 58 Python 学习从入门到实践(第2 版) 个双分支结构。 (2)运行后,如果x>y,则执行if结构下的print("较大的是:",x)语句;否则执行 else结构下的print("较大的是:",y)语句。注意如果输入的两个数字相等,使用此结构 和例3.1的结果不同,因为使条件判断x>y为假的情况可能是x: <语句块1> elif <条件2>: <语句块2> elif <条件3>: <语句块3> .e lse: <语句块n> 程序执行时,会按照条件n的序列从上往下进行判断,当第一个条件i的值为True 时,就执行该条件下的语句块,然后整个多分支if结构结束。如果没有任何条件为True, 则执行else下的语句块。注意else是可选的。 【例3.3】 用多分支结构改写例3.1,如果两个数字相等,也要给出说明。 程序代码如下: #example3.3 x = eval(input("请输入第一个数字:")) y = eval(input("请输入第二个数字:")) print("输入的两个数字为:",x,y) if x>y: print("较大的是:",x) elif xy和x= 90: gpa = 4 elif score >= 80: gpa = 3 elif score >= 70: gpa = 2 elif score >= 60: gpa = 1 else: gpa = 0 print("应得学分绩点为:",gpa) 程序2代码如下: #example3.42 score = eval(input("请输入分数:")) if score < 60: gpa = 0 elif score >= 60: gpa = 1 elif score >= 70: gpa = 2 elif score >= 80: 60 Python 学习从入门到实践(第2 版) gpa = 3 else: gpa = 4 print("应得学分绩点为:",gpa) 程序1运行结果如下(输入85): >>> ======= RESTART: C:/Python/Python36/example3.41.py ======= 请输入分数:85 应得学分绩点为:3 >>> 程序2运行结果如下(输入85): >>> ======= RESTART: C:/ Python/Python36/example3.42.py ======= 请输入分数:85 应得学分绩点为:1 >>> 说明:经过比较可以看出,虽然两段程序都可以顺利执行,但是程序2并不符合题目 的要求。例如在输入85时,程序1可以得出gpa为3,而程序2得出的gpa只有1,原因 就是在程序2中,进行score>60的判断结果为True时,将gpa赋值为1,然后就结束了 整个多分支结构。 使用多分支if语句时一定要注意思路清晰,要养成良好的程序书写风格,层次明确, 使得程序便于阅读和修改。 3.2.4 分支结构的嵌套 如果一个if分支结构中包含另一个(或多个)if分支,则称为分支结构的嵌套。 【例3.5】 输入3个数字,利用分支结构对其进行降序排列输出。 程序代码如下: #example3.5 a= eval(input("输入第1 个数字")) 第3 章 Python 控制语句 61 b= eval(input("输入第2 个数字")) c= eval(input("输入第3 个数字")) print("输入顺序为:",a,b,c) if ab: print("排序后为:",a,c,b) else: print("排序后为:",a,b,c) 程序运行结果如下: >>> ======= RESTART: C: /Python/Python36/example3.5.py ======= 输入第1 个数字5 输入第2 个数字3 输入第3 个数字4 输入顺序为:5 3 4 排序后为:5 4 3 >>> 说明: (1)先比较输入的前两个数字a、b的大小,如果a小于b,则交换a、b的顺序,第一个 单分支结构保证了a一定要大于b。 (2)在双分支结构中,如果ac,则再用一个双分支来判断b和c的大小,如果b>c,则按照a、b、c的顺序 输出排序结果;如果bin <遍历结构>: <语句块> for语句的执行过程是:每次循环,判断循环变量是否还在遍历结构中,如果在,取出 该值提供给循环体内的语句使用;如果不在,则结束循环。 【例3.6】 求1到100之间的奇数和。 程序1代码如下: #example3.61 s= 0 for i in range(1,101,2): s = s+i print("1 到100 之间的奇数和为:",s) 程序运行结果如下: >>> ======= RESTART: C: /Python/Python36/example3.61.py ======= 1 到100 之间的奇数和为:2500 >>> 程序2代码如下: #example3.62 s= 0 for i in range(1,101): if i %2 == 1: s = s+i print("1 到100 之间的奇数和为:",s) 第3 章 Python 控制语句 63 程序运行结果如下: >>> ======= RESTART: C: /Python/Python36/example3.62.py ======= 1 到100 之间的奇数和为:2500 >>> 说明如下。 (1)程序1定义一个初始值为0的变量s,然后通过range()函数产生1到100之间 的奇数值,利用循环变量取遍这些值,然后将它们加到s中。 (2)range()函数可以产生某范围内的整数,如果只有一个参数,例如range(5),产生 从0到5之间的整数,包括0但是不包括5,即[0,4];如果有两个参数,例如range(3,7), 产生的数字范围为[3,6];如果有三个参数,则第三参数代表步长值,即从初值到终值过渡 时每次加的数字,例如range(5,12,2)产生的数字列表为[5,7,9,11],range()函数也可以 产生一个由大到小的数字列表,但是步长参数要为负数,例如range(10,5,-1)产生的数 字为[10,9,8,7,6]。 (3)程序1中for语句执行时,range(1,101,2)函数产生[1,100]间,并且由1开始每 次加数字2的遍历结构,直到等于101结束,而循环变量i每次遍历其中一个数字,通过 s=s+i语句累加到变量s中。 (4)程序2定义一个初始值为0的变量s,然后通过range()函数产生1到100之间 所有的整数,利用循环变量取遍这些值,再通过分支语句if判断这些值是不是奇数,如果 是奇数,就加到s中。 (5)程序2中,range(1,101)只负责产生[1,100]内的整数,i遍历取遍这些数字,由if 语句来判断这些数字中哪些是奇数,如果满足i%2==1这个条件,就累加到s中,虽然 这段代码用了循环嵌套分支的结构,相比程序1更复杂,但是这段代码更具有通用性,可 以解决的问题种类更多。 for语句循环还可以使用else关键字,其语法格式如下: for <循环变量>in <遍历结构>: <语句块1> else: <语句块2> 在这种结构中,当for循环正常执行之后,程序会继续执行else语句中的内容。如果 for循环因为某种原因没有正常执行完,例如遇到了break语句,则不会执行else语句中 64 Python 学习从入门到实践(第2 版) 的内容。所以通常用else来检验for循环是否结束。例3.6中的程序2也可以改为以下 格式: #example3.62 s = 0 for i in range(1,101): if i %2 == 1: s = s+i else: print("计算完毕。",end=““) print("1 到100 之间的奇数和为:",s) 程序运行结果如下: >>> ======= RESTART: C: /Python/Python36/example3.62.py ======= 计算完毕。1 到100 之间的奇数和为:2500 >>> 需要注意的是,在使用else的循环中,else语句要和for对齐,而不是和for循环中的 if语句对齐。 【例3.7】 求字符串“Lifeisshort,YOUneedPython!”中有多少个字母o,不区分 大小写字母。 程序代码如下: #example3.7 n = 0 str = "Life is short, YOU need Python!" for i in str: ifI == "o" or I == "O": n = n + 1 else: print("计算完毕。",end = "") print("字母o 的个数为:",n) 代码执行结果如下: 第3 章 Python 控制语句 65 >>> ======= RESTART: C: /Python/Python36/example3.7.py ======= 计算完毕。字母'o'的个数为:3 >>> 说明:先设置一个初始值为0的变量n作为计数器,然后将字符串作为一个遍历结 构,循环变量i会每次取字符串中的一个字母,再判断该字母是不是o或O,如果是,将n 增加1。 3.3.2 while循环 在明确知道循环的次数或者明确遍历结构时,一般使用for循环。但是更多时候遍 历结构无法明确,或者不确定循环需要进行多少次。这时,就要使用while循环了。 while循环语法格式如下: while <条件>: <语句块> 其中<条件>结果为True或者False。如果条件为True,则执行一遍语句块,然后 返回while语句继续判断<条件>;当条件为False时循环结束。 与for一样,while循环也有一种带有else的表达形式,语法格式如下: while <条件>: <语句块1> else: <语句块2> 在这种结构中,当while循环正常结束后,程序会继续执行else语句中的语句块2,一 般用来检验while循环是否结束。 【例3.8】 猜价格。首先产生一个[10,100]内的随机整数作为价格并赋予一个变量 n。然后用户可以输入数字猜价格,如果输入的数字大于n或者小于n,则给用户相应的 提示;如果猜对了,则告诉用户猜中了。 程序代码如下: #example3.8 from random import randint 66 Python 学习从入门到实践(第2 版) n = randint(10,100) print("商品价格已经产生,请输入10 到100 间的价格:") bingo = False while bingo == False: guess = eval(input("请输入您猜的价格:")) if guess > n: print("您输入的价格高于指定价格,请继续。") elif guess < n: print("您输入的价格低于指定价格,请继续。") else: print("恭喜您猜对了!价格为",guess) bingo = True else: print("游戏结束!") 程序运行的结果为: >>> ======= RESTART: C: /Python/Python36/example3.8.py ======= 商品价格已经产生,请输入10 到100 间的价格。 请输入您猜的价格:80 您输入的价格低于指定价格,请继续。 请输入您猜的价格:90 您输入的价格高于指定价格,请继续。 请输入您猜的价格:85 您输入的价格低于指定价格,请继续。 请输入您猜的价格:88 您输入的价格低于指定价格,请继续。 请输入您猜的价格:87 恭喜您猜对了!价格为87 游戏结束! >>> 说明如下。 (1)产生一个随机整数,可以引用函数库random 中的randint(m,n)函数,参数 m<=n,函数会产生[m,n]内的随机整数。 (2)当程序进入while循环时,判断条件bingo=False为真值,意味着开始循环。循 第3 章 Python 控制语句 67 环中使用input()函数为变量guess赋值,然后用多分支if对guess进行判断,当guess的 值大于或者小于n时,都给予文字提示,然后分支结束,返回while语句继续循环;当 guess的值等于n,多分支结构if结构执行else下的语句:输出“恭喜您猜对了!”并且把 bingo变量赋值为True,分支结束。当返回while语句时,bingo=False就变成了假值,循 环结束,执行while语句同层的else下的语句。 (3)本例中,循环是依靠一个条件“输入价格不等于初始产生的价格”进行的,由于用 户输入的数字次数即猜价格的次数未知,所以不能采用for循环结构。而while循环结构 就可以处理这种未知循环次数的循环。 当然,while循环也可以用来编写已知循环次数的循环。用while循环构造一个数字 范围,一般是在while语句之前定义循环变量的初始值;在循环语句中指定循环变量的步 长值;在while语句的条件处设置循环的终止值。 【例3.9】 用while循环求100以内的奇数和。 程序代码如下: #example3.9 s = 0 i = 1 whilei <= 100: if i %2 == 1: s = s + i i += 1 else: print("计算完毕。",end = '') print ("1 到100 之间的奇数和为:",s) 程序运行结果如下: >>> ======= RESTART: C: /Python/Python36/example3.9.py ======= 计算完毕。1 到100 之间的奇数和为:2500 >>> 说明:i=1的作用是定义循环变量初始值,在while条件处设置i<=100为循环变 量的终止值,在循环中i+=1语句和i=i+1等价,设置每次i增加的步长。 在编写while循环时,如果条件的计算结果一直为True,而循环中没有break来结束 while循环,也就是没有逻辑出口,循环将陷入永远执行的状态,称为死循环。例如以下 68 Python 学习从入门到实践(第2 版) 两行语句组成的程序将一直输出数字3。 while True: print(3) 在例3.9中,如果删除i=i+1语句,i值在每次循环时都是1,而循环条件是i<= 100,每次判断时都为True,循环将始终执行。如果程序陷入死循环,在IDLE环境中可 以按组合键Ctrl+C,开发环境中会显示KeyboardInterrupt信息,程序终止。 3.3.3 循环的嵌套 在循环语句中使用另一个循环语句称为循环的嵌套,也称多重循环。for循环和 while循环都可以互相嵌套。利用循环的嵌套可以实现更复杂的程序设计,例如以下代 码段: for i in range(1,4): for j in range(1,4): print("i 值为",i,";","j 值为",j) 可以看到,程序段的运行结果为: i 值为1 ; j 值为1 i 值为1 ; j 值为2 i 值为1 ; j 值为3 i 值为2 ; j 值为1 i 值为2 ; j 值为2 i 值为2 ; j 值为3 i 值为3 ; j 值为1 i 值为3 ; j 值为2 i 值为3 ; j 值为3 上层的i循环称为外层循环,下层的j循环称为内层循环,当外层循环执行一次时,内 层循环就要整体循环一遍。从上面程序的结果可以看出,当外层循环的循环变量i为1 时,内层循环就要完成循环变量j从1到3的取值,当内层循环结束后,再次返回外层循 环,i值变为2,内层循环再完整循环一次,以此类推。如果把两个循环加上else语句,程 序代码如下: 第3 章 Python 控制语句 69 for i in range(1,4): for j in range(1,4): print("i 值为",i,";","j 值为",j) else: print("内层循环结束。") else: print("外层循环结束。") 程序的运行结果如下: i 值为1 ; j 值为1 i 值为1 ; j 值为2 i 值为1 ; j 值为3 内层循环结束。 i 值为2 ; j 值为1 i 值为2 ; j 值为2 i 值为2 ; j 值为3 内层循环结束。 i 值为3 ; j 值为1 i 值为3 ; j 值为2 i 值为3 ; j 值为3 内层循环结束。 外层循环结束。 可以看出,外层循环结束一次,而内层循环一共结束了3次。 【例3.10】 解中国古代一道著名的数学题———百元百鸡问题。已知公鸡5元1只; 母鸡3元1只;小鸡1元3只。问要想用100元正好买100只鸡,该如何购买? 程序代码如下: #example3.10 for x in range(1,21): for y in range(1,34): z = 100-x-y if 5*x+3*y+z/3 == 100: print("公鸡",x,"母鸡",y,"小鸡",z) else: print("计算完毕") 70 Python 学习从入门到实践(第2 版) 程序运行结果如下: >>> ======= RESTART: C: \Python\Python36\例题3.10.py ======= 公鸡4 母鸡18 小鸡78 公鸡8 母鸡11 小鸡81 公鸡12 母鸡4 小鸡84 计算完毕 >>> 说明如下。 (1)如果用列方程的方法来解决,可以知道只能根据鸡的数量等于100或者钱的数 量等于100列出两个方程,而问题有3个未知数,无法求得具体的值。在计算机中,可以 采用穷举法求解,即对所有可能解逐个进行试验,若满足条件,就得到一组解,否则继续测 试,直到循环结束为止。 (2)假设公鸡有x只,则100元全部买公鸡的话,最多可以买20只,如果最少需要买 一只公鸡的话,那么x的取值范围为range(1,21);假设母鸡有y只,则100元全部买母鸡 的话,最多可以买33只,如果母鸡最少需要买1只,那么y的取值范围为range(1,34),利 用双重循环组合x和y的值,当x和y确定为某一个数值后,小鸡的数量如果用z来代 表,则z的值为100-x-y,每次循环都测试条件5*x+3*y+z/3=100是否成立, 如果条件成立,则找到一组合适的解。 和分支结构的嵌套一样,编写循环的嵌套时,要注意语句或者语句段的所属层次,认 清外层循环中的语句还是内层循环中的语句。 3.4 break 语句和continue 语句 3.4.1 break语句 Python提供了一个提前结束循环的语句———break语句。在循环中,执行到break 语句时,可以结束本层的循环。一般来说,break语句要放在一个分支结构中,当触发某 个条件时,结束循环的运行。例如有如下代码: for s in "python": for i in range(1,4): print(s,end = "") 第3 章 Python 控制语句 71 其作用是把"python"中的每个字母都重复3遍,不换行输出。程序运行结果如下: >>> ======= RESTART: C:/Python/Python36/temp.py ======= pppyyyttthhhooonnn >>> 修改代码如下: for s in "python": for i in range(1,4): if s == "h": break print(s,end = "") 程序运行结果如下: >>> ======= RESTART: C:/Python/Python36/temp.py ======= pppyyytttooonnn >>> 说明如下。 (1)在内层循环中,如果s等于字母h,则跳出内层循环。但是外层循环将继续运行, 程序依然会输出字母h以后的字母o和字母n。 (2)使用break时,要注意这条语句属于哪个循环。 【例3.11】 求两个数字的最小公倍数。 程序代码如下: x = eval(input("输入第一个数字")) y = eval(input("输入第二个数字")) if x < y: x,y = y,x for i in range(x,x*y+1): if i%x == 0 and i%y == 0: print(x,"和",y,"的最小公倍数为",i) break