第3章
程序控制结构



程序是一组相关命令的集合,它以文件的形式存储在磁盘中,其文件的扩展名为“.py”。
3.1程 序 基 础
3.1.1Python程序的构成

Python程序文件一般包括注释、模块导入、函数定义和程序主体等部分,如图31所示。


图31Python程序文件的基本构成


(1) 注释
注释是在代码中加入的一行或多行信息,用来对模块、函数、方法等进行说明,用以提升代码的可读性。注释是用于辅助程序阅读或编写的,编译器或解释器会略去注释部分的内容。Python中的注释有单行注释和多行注释两种。Python中的单行注释以#作为开始标记,可以单独占一行,也可以写在程序代码行的后面,#后的部分即为注释部分,一般用于对该行或该行中部分代码的解释。多行注释用三个'''或者三个双引号"""将注释括起来。
(2) 模块导入
若程序中需要用到标准库或第三方库的功能,则需要先将库导入。
(3) 函数定义
函数定义部分一般能够完成一个相对独立的子功能,由程序主体或其他函数调用执行。
(4) 程序主体
程序主体是完成程序功能的主要部分,程序文件需要按照程序主体部分的语句来依次执行。
3.1.2Python中的缩进
Python程序大小写敏感、缩进敏感。缩进指每一行代码开始前的空白区域,用来表示代码之间的包含和层次关系。Python是通过缩进来识别代码块的,因此对缩进非常敏感,对代码格式要求也非常严格。对于不同级别的代码,位于同一个代码块中的所有语句必须保持相同的缩进,没有缩进或者缩进量不对都会产生错误。Python可以使用Tab键或4个空格缩进一级。

3.1.3程序基本结构分类
程序在计算机上执行时,程序中的语句完成具体的操作并控制执行流程。程序中语句的执行顺序称为程序结构。
程序包含3种基本结构: 顺序结构、分支结构和循环结构。顺序结构是指程序中的语句按照出现位置顺序执行; 分支结构是指程序中的某些语句按照某个条件来决定执行与否; 循环结构是指程序中的语句在某个条件下重复执行多次。
3.2顺 序 结 构
顺序结构是比较简单的一种结构,也是常用的一种结构,其语句是按照位置顺序执行的。如图32所示,顺序结构中的语句块1、语句块2按位置顺序依次执行。


图32顺序结构

流程图

【例31】编写程序,通过输入正方体的边长a,求正方体的体积。
首先对该题目进行分析,程序的输入、处理和输出三个部分分别可以表示为: 
输入: 正方体的边长a
处理: 正方体的体积v=a3
输出: 正方体的体积v
依据输入、输出和处理过程编写程序代码,参考代码如下:




1#E3-1.py

2#计算正方体的体积

3a=eval(input("输入正方体的边长a:"))

4v=a**3

5print("正方体的体积为:", round(v,2))







程序运行结果如下: 



输入正方体的边长a: 3.5

正方体的体积:  42.88






【例32】用顺序结构编程求解一元二次方程y=3x2+5x+7,要求通过输入x的值求得y的值。
参考代码如下: 



1#E3-2.py

2#求解一元二次方程

3x=eval(input("输入x的值: "))

4y=3*x**2+5*x+7

5print("y的值是: ",y)






程序运行结果如下: 



输入x的值: 3

y的值是: 49






【例33】编写程序,输入4个数,并求它们的平均值。
参考代码如下: 



1#E3-3.py

2#求平均值

3x1,x2,x3,x4=eval(input("输入4个数(逗号分隔): "))

4avg=(x1+x2+x3+x4)/4

5print(avg)






程序运行结果如下: 


图33用turtle绘制

扇形




输入4个数(逗号分隔): 15,23,6,7

12.75






【例34】用turtle绘制图33所示扇形,其中扇形的半径为200,圆心角为120 ,填充颜色为红色。
参考代码如下: 



1#E3-4.py

2#用turtle绘制扇形

3import turtle

4turtle.hideturtle()

5turtle.fillcolor("red")

6turtle.begin_fill()

7turtle.fd(200)

8turtle.left(90)

9turtle.circle(200,120)

10turtle.left(90)

11turtle.fd(200)

12turtle.end_fill()






3.3分 支 结 构
分支结构也称为选择结构,该结构可以通过判断某些特定条件是否满足来决定下一步的执行流程。分支结构是非常重要的一种结构。常见的分支结构有单路分支结构、双路分支结构和多路分支结构。
3.3.1单路分支结构
单路分支结构是分支结构中最简单的一种形式,其语法格式如下所示。

if <条件表达式>:

<语句块>

其中: 
 单路分支结构以if开头,后接<条件表达式>。
 <条件表达式>可以是关系表达式、逻辑表达式、算术表达式等。
 冒号“:”表示一个语句块的开始,不能缺少。
 <语句块>可以是单个语句,也可以是多个语句。相对于“if”的位置,缩进为4个字符。


图34单路分支结构

流程图

功能: 当<条件表达式>的值为True时,执行语句块; 若为False,则不做任何操作。其流程图如图34所示。
在判断<条件表达式>的布尔值时,若<条件表达式>的值为数值0、空字符串、空元组、空列表、空字典的布尔值均为False,其余为True。该判断方法适用于后续所有分支结构和循环结构中对<条件表达式>部分的判断。
【例35】输入一个整数,如果是偶数,则输出“这是个偶数”,否则无输出。
参考代码如下: 



1#E3-5.py

2#单分支输出"这是个偶数"

3s=eval(input("请输入一个整数: "))

4if s%2==0:

5print("这是个偶数")






运行程序,输入一个偶数,程序运行结果如下: 



请输入一个整数: 6

这是个偶数






再次运行程序,输入一个奇数,程序运行结果如下: 



请输入一个整数: 3






【例36】输入腋下体温值t,根据如下情况分别输出: 

t<36.1输出: 您的体温偏低

36.1<=t<=37  输出: 您的体温正常

37<t         输出: 您的体温偏高

参考代码如下: 



1#E3-6.py

2#体温判断

3t=eval(input("请输入腋下体温值: "))

4if t<36.1:

5print("您的体温偏低")

6if 36.1<=t<=37:

7print("您的体温正常")

8if 37<t:

9print("您的体温偏高")







运行程序,输入35,程序运行结果如下: 



请输入腋下体温值: 35

您的体温偏低






运行程序,输入36.7,程序运行结果如下: 



请输入腋下体温值: 36.7

您的体温正常






运行程序,输入38.5,程序运行结果如下: 



请输入腋下体温值: 38.5

您的体温偏高






【例37】输入两个整数x、y,请将这两个数由小到大输出。
参考代码如下: 



1#E3-7.py

2#两个数排序

3x,y=eval(input("请输入x、y: "))

4if x>y:

5x,y=y,x

6print(x,y)






运行程序,依次输入5、3,程序运行结果如下: 



请输入x、y: 5,3

3 5






【例38】输入3个整数x、y、z,请将这3个数由小到大输出。
参考代码如下: 



1#E3-8.py

2#三个整数排序

3x,y,z=eval(input("输入3个数(用逗号分隔):"))

4if x>y:

5x,y=y,x

6if x>z:

7x,z=z,x

8if y>z:

9y,z=z,y

10print(x,y,z)






运行程序,依次输入3、16、-5,程序运行结果如下: 



输入3个数(用逗号分隔):3,16,-5

-5 3 16






思考: 若第6行代码改为“if y>z:”,那么后续代码应如何编写?
3.3.2双路分支结构
双路分支结构是程序中比较常用的一种形式,其语法格式如下所示。

if <条件表达式>:

<语句块1>

else:

<语句块2>

其中: 
 双路分支结构以if开头,后接<条件表达式>。
 <条件表达式>可以是关系表达式、逻辑表达式、算术表达式等。
 冒号“:”: 表示一个语句块的开始,不能缺少。
 <语句块1>/<语句块2>可以是单个语句,也可以是多个语句。相对于“if”和“else”的位置,缩进为4个字符。


图35双路分支结构流程图

功能: 当<条件表达式>的值为True时,执行if后的<语句块1>,继而双路分支语句结束; 若为False,则执行else后的<语句块2>,分支语句结束。其流程图如图35所示。
【例39】输入一个整数,如果是偶数,则输出“这是个偶数”,否则输出“这是个奇数”。
参考代码如下: 



1#E3-9.py

2#双路分支判断奇偶








3s=eval(input("请输入一个整数: "))

4if s%2==0:

5print("这是个偶数")

6else:

7print("这是个奇数")






运行程序,输入整数6,程序运行结果如下: 



请输入一个整数: 6

这是个偶数






运行程序,输入整数3,程序运行结果如下: 



请输入一个整数: 3

这是个奇数






【例310】输入x的值,计算y=x2-25x≤-5或x≥5

25-x2-5<x<5中y的值。
参考代码如下: 



1#E3-10.py

2#按条件求解表达式的值

3x=eval(input("输入一个整数: "))

4if x<=-5 or x>=5:

5y=(x**2-25)**0.5

6else:

7y=(25-x**2)**0.5

8print(y)






运行程序,输入整数-15,程序运行结果如下: 



输入一个整数: -15

14.142135623730951






运行程序,输入整数2,程序运行结果如下: 



输入一个整数: 2

4.58257569495584






运行程序,输入整数15,程序运行结果如下: 



输入一个整数: 15

14.142135623730951






注: 此处也可以通过导入math库,利用sqrt()函数求解平方根。


图36用turtle绘制圆形

【例311】输入一个数,利用turtle库绘制如图36所示圆形,当输入的数是偶数时,填充颜色为蓝色; 当输入的数是奇数时,填充颜色为红色。画笔大小为5,圆的半径为100。
参考程序代码: 



1#E3-11.py

2#用turtle绘制圆形

3import turtle

4x=eval(input("输入一个整数:"))

5if x%2==0:

6turtle.fillcolor("blue")

7else:

8turtle.fillcolor("red")

9turtle.pensize(5)

10turtle.hideturtle()

11turtle.begin_fill()

12turtle.circle(100)

13turtle.end_fill()






运行程序文件,当输入偶数时,绘制的是蓝色圆形; 当输入奇数时,绘制的是红色圆形。
双路分支结构还可以用表达式的形式实现,语法格式如下所示。

<表达式1> if <条件表达式> else <表达式2>

功能: 当<条件表达式>的值为True时,执行<表达式1>; 当<条件表达式>的值为False时,执行<表达式2>。
【例312】输入一个数,如果这个数是10,则输出“猜对了”,否则输出“猜错了”。
参考代码如下: 



1#E3-12.py

2#猜数

3guess=eval(input())

4y="猜对了" if guess==10 else "猜错了"

5print(y)






运行程序,输入数字10,程序运行结果如下: 



10

猜对了






运行程序,输入数字5,程序运行结果如下: 



5

猜错了






【例313】用双路分支的表达式形式改写例39。
参考代码如下: 



1#E3-13.py

2#单行形式判断奇偶

3s=eval(input("请输入一个整数: "))

4y="偶数" if s%2==0 else "奇数"

5print(y)






运行程序,输入整数6,程序运行结果如下: 



请输入一个整数: 6

偶数






运行程序,输入整数3,程序运行结果如下: 



请输入一个整数: 3

奇数






3.3.3多路分支结构
多路分支结构是双路分支结构的扩展,其语法格式如下所示。

if <条件表达式1>:

<语句块1>

elif <条件表达式2>:

<语句块2>

……

elif <条件表达式n>:

<语句块n>

[else:

<语句块n+1>]


其中: 
 多路分支结构以if开头,后接<条件表达式>。
 <条件表达式1>/…/<条件表达式n>可以是关系表达式、逻辑表达式、算术表达式等。
 冒号“:”表示一个语句块的开始,不能缺少。
 <语句块1>/…/<语句块n>可以是单个语句,也可以是多个语句。相对于“if”“elif”和“else”的位置,缩进为4个字符。
 方括号部分可以省略。
功能: 当<条件表达式1>的值为True时,执行if后的<语句块1>,继而多路分支语句结束; 若<条件表达式1>的值为False,则继续判断elif后<条件表达式2>的值。若<条件表达式2>的值为True,执行<语句块2>,多路分支语句结束; 若为False,则继续判断elif后<条件表达式3>的值,以此类推。如果所有条件表达式均不成立,则执行else部分的<语句块n+1>,多路分支语句结束。其流程图如图37所示。


图37多路分支结构流程图


【例314】编写程序: 输入学生成绩,根据成绩所在区间进行分类输出。
90分以上输出: 优秀
80~89分 输出: 良好
70~79分 输出: 中等
60~69分 输出: 及格
低于60分  输出: 不及格
参考代码如下: 



1#E3-14.py

2#根据成绩区间分类输出

3score=eval(input("请输入学生成绩: "))

4if score>=90:

5print("优秀")

6elif score>=80:

7print("良好")

8elif score>=70:

9print("中等")

10elif score>=60:

11print("及格")

12else:

13print("不及格")






运行程序,输入学生成绩为69,程序运行结果如下: 



请输入学生成绩: 69

及格






运行程序,输入学生成绩为75,程序运行结果如下: 



请输入学生成绩: 75

中等






运行程序,输入学生成绩为97,程序运行结果如下: 



请输入学生成绩: 97

优秀






【例315】从键盘输入一个字符ch,判断它是英文字母、数字或其他字符。
根据题目要求,分析输入字符的三种情况: 
(1) 英文字母: ch>="a" and ch<="z" or ch>="A" and ch<="Z"。
(2) 数字字符: ch>"0" and ch<="9"。
(3) 其他字符: 排除(1)和(2)两种情况的情况。
参考代码如下: 



1#E3-15.py

2#判断输入字符种类

3ch=input("请输入一个字符: ")

4if ch>='a' and ch<='z' or ch>='A' and ch<='Z':

5print("{}是英文字母".format(ch))

6elif ch>='0' and ch<='9':

7print("{}是数字".format(ch))

8else:

9print("{}是其他字符".format(ch))






运行程序,输入字母m,程序运行结果如下: 



请输入一个字符: m

m是英文字母






运行程序,输入数字7,程序运行结果如下: 



请输入一个字符: 7

7是数字






运行程序,输入其他字符*,程序运行结果如下: 



请输入一个字符: *

*是其他字符






【例316】编写程序,输入员工号和该员工的工作时数,计算并输出员工的应发工资。工资计算方法如下: 
(1) 月工作时数超过150小时者,超过部分加发15%。
(2) 月工作时数低于100小时者,扣发500元。
(3) 其余情况按每小时60元发放。
参考代码如下: 



1#E3-16.py

2#计算不同情况下员工工资

3num=input("员工号: ")

4h=eval(input("工作时数: "))

5s=0








6if h>150:

7s=(h+(h-150)*0.15)*60

8elif h<100:

9s=h*60-500

10else:

11s=h*60

12print("{}员工的应发工资是{}元".format(num,s))






输入员工号3001、工作时数160,程序运行结果如下: 



员工号: 3001

工作时数: 160

3001员工的应发工资是9690.0元






输入员工号3002、工作时数120,程序运行结果如下: 



员工号: 3002

工作时数: 120

3002员工的应发工资是7200元






输入员工号3003、工作时数85,程序运行结果如下: 



员工号: 3003

工作时数: 85

3003员工的应发工资是4600元






3.4循 环 结 构
在程序设计过程中,经常需要将一些代码按照要求重复多次执行,这时就需要用到循环结构。Python有两种类型的循环语句,分别是for循环和while循环。for循环为确定次数的循环,while循环为非确定次数的循环。
3.4.1for循环结构
1. for语句的一般格式
for循环结构是循环控制结构中使用较广泛的一种循环控制语句。for循环以遍历序列对象的方式构造循环,特别适用于循环次数确定的情况,其语法格式如下所示。

for <变量> in <序列对象>:

<循环体>

其中: 
 <变量>用于控制循环次数,也可以参与到循环体中。
 <序列对象>中一般以某种方式存储多个序列对象,例如,字符串、列表、元组、集合、文件等都可以作为序列对象,也可以使用range()产生序列对象。
 <循环体>中的语句是需要重复执行的部分。


图38for循环流程图

功能: 从<序列对象>中选取元素,如果有元素待选取,则执行<循环体>,并在执行<循环体>后,继续尝试从<序列对象>中选取元素; 如果<序列对象>没有元素待选取,则结束循环。其流程图如图38所示。
2. range()
range()是Python的内建对象,可以创建一个整数列表,一般用在for循环中。range()共有三个参数: start、stop和step,其中start和step可以缺省。其语法格式如下。

range([start,] stop[, step])

其中: 
 start表示计数开始的数值,缺省时为0。
 stop表示结束但不包括的数值。
 step表示步长,缺省时为1。
功能: range()表示生成一个从start值开始,到stop值结束(但不包含stop)的range对象。
例如: 
range(5)等价于range(0,5,1),生成的数值为0,1,2,3,4。
range(2,18,3)生成的数值为2,5,8,11,14,17。
说明: range()返回的是一个可迭代对象,其类型为“range”,而不是列表,所以使用print()语句对其打印的时候不会打印列表。
3. for语句的应用
for语句经常与range()函数配合使用,实现循环从一个数字开始,到另一个数字结束。
【例317】循环输出数值0~5。
参考代码如下: 



1#E3-17.py

2#循环输出数值0~5

3for i in range(6):

4print(i,end=',')






程序运行结果如下: 



0,1,2,3,4,5,






【例318】循环输出1~10之间的奇数。
参考代码如下: 



1#E3-18.py

2#循环输出1~10之间的奇数

3for i in range(1,11,2):

4print(i,end=' ')






程序运行结果如下: 



1 3 5 7 9






【例319】利用循环求解1~100的累加和。
分析: 利用range()构造100次循环,即变量i从1到100循环递增。每循环一次将变量i的值累加到变量s中。当循环结束时,s中保存的就是1到100的累加和。
参考代码如下: 



1#E3-19.py

2#求1~100的累加和

3s=0

4for i in range(1,101):

5s += i

6print("1+2+3+...+100=",s)






程序运行结果如下: 

1+2+3+...+100= 5050

【例320】使用turtle库绘制红色五角星图形,效果如图39所示,五角星非相邻两个顶点间的距离为200。
分析: 如图310所示,绘制过程以S为起始点绘制直线,长度为200,此时到达五角星的另外一个顶点,然后向右转144°,再继续绘制直线,长度为200,如此反复5次,最终绘制出五角星。绘制顺序如图310中箭头方向所示。



图39用turtle绘制五角星




图310绘制五角星方法



参考代码如下: 



1#E3-20.py

2#绘制五角星

3from turtle import *

4setup(400,400)

5penup()

6goto(-100,50)

7pendown()








8color("red")

9begin_fill()

10for i in range(5):

11forward(200)

12right(144)

13end_fill()

14hideturtle()

15done()






for语句还经常用于字符串、列表等组合数据类型的遍历,组合数据类型将在第4章详细介绍。这里将给出一些简单的实例。
【例321】输出字符串"PythonStudy"中的每个字符,并用空格分隔,即输出PythonStudy。
参考代码如下: 



1#E3-21.py

2#循环输出字符串

3for i in "PythonStudy":

4print(i,end=' ')






程序运行结果如下: 



P y t h o n S t u d y






【例322】循环输出列表["11350675","白萌萌","女",660]中的元素。
参考代码如下: 



1#E3-22.py

2#列表的遍历

3for st in ["11350675","白萌萌","女",660]:

4print(st,end='-')






程序运行结果如下: 



11350675-白萌萌-女-660-






for语句还可以对文件进行遍历,文件将在第7章介绍。
3.4.2while循环结构
while循环结构也可以完成for循环结构的功能,但不如for循环结构简单直观。while循环结构主要用于构造恒真循环和不确定运行次数的循环。其语法格式如下所示。

while <条件表达式>:

<循环体>

 <条件表达式>可以是关系表达式、逻辑表达式、算术表达式等。
 <循环体>中的语句是需要重复执行的部分。


图311while循环流程图

功能: while循环结构首先判断<条件表达式>的值,如果为True,则重复执行<循环体>,直到<条件表达式>的值为False时,结束循环。其流程图如图311所示。
说明: 在while语句的循环体中一定要包含改变测试条件的语句或break语句,以避免死循环的出现,保证循环能够结束。
【例323】用while循环改写例317。
参考代码如下: 



1#E3-23.py

2#改写例3-17

3i=0

4while i<6:

5print(i,end=',')

6i=i+1






思考: 若此处没有语句i=i+1,则代码执行时会出现什么问题? 
【例324】从键盘输入若干个数,求所有正数之和。当输入0或负数时,程序结束。
参考代码如下: 



1#E3-24.py

2#求若干个数的和

3s=0

4x=eval(input("请输入一个正整数:"))

5while x>0:

6s=s+x

7x=eval(input("请输入一个正整数:"))

8print("s=",s)






运行程序,依次输入15、3、48、26、0,程序运行结果如下: 



请输入一个正整数:15

请输入一个正整数:3

请输入一个正整数:48

请输入一个正整数:26

请输入一个正整数:0

s= 92






3.4.3break、continue和pass
break、continue和pass语句在for循环和while循环中都可以使用,并且在循环体中一般与选择结构配合使用,以达到满足特定条件时执行的效果。
(1) break语句
break语句的作用是终止循环的执行,如果循环中执行了break语句,循环就会立即终止。
(2) continue语句
continue语句的作用是立即结束本次循环,开始下一轮循环,也就是说,跳过循环体中在continue语句之后的所有语句,并根据条件判断是否继续下一轮循环。对于for循环,执行continue语句后将<序列对象>中的下一个元素赋值给<变量>; 对于while循环 ,执行continue语句后将转到<条件表达式>判断部分。
(3) pass语句
pass语句是空语句,不做任何操作事情,一般用作占位语句,保证程序结构的完整。例如,如果只是想利用循环延迟后续程序的执行时间,可以让程序循环一定次数却什么都不做。然而循环体可以包含一个语句或多个语句,但是不可以没有任何语句,此时就可以使用pass语句。与break和continue不同的是,pass语句不仅可以用在循环结构中,也可以用在顺序结构和选择结构中。
【例325】将字符串“BIYE”中的字符“I”去掉,并输出其他字符。
参考代码如下: 



1#E3-25.py

2#去掉字符并输出

3for k in "BIYE":

4if k=="I":

5continue

6print(k,end="")






程序运行结果如下: 



BYE






扩展: 若用break代替例325中的continue,会有什么样的结果?
针对这一问题,改写程序如下所示: 



1#E3-25扩展.py

2#去掉字符并输出

3for k in "BIYE":

4if k=="I":

5break

6print(k,end="")






程序运行结果如下: 



B






分析: 在例325中,程序执行到continue时,会跳转到下一次循环,由于字符“I”后面还有其他字符,所以会继续执行。若将continue的位置替换为break,由于break语句会跳出循环,所以程序执行结束,后面的字符不再访问。
3.4.4循环结构的else语句
无论是for循环还是while循环都支持else语句,具体格式如下: 


for <变量> in <序列对象>:

<循环体>

[else:

<语句块>]
while <条件表达式>:

<循环体>

[else:

<语句块>]

else所在的方括号部分可以省略。如果循环因为<条件表达式>不成立而自然结束,则执行else结构中的<语句块>; 如果循环是因为执行了break语句而导致提前结束,则不执行else中的<语句块>。
由于两种循环的else语句部分用法相似,所以我们以for循环中的else语句为例进行介绍。
【例326】将字符串“BIYE”中的字符“I”去掉,并输出其他字符。若for循环完成遍历,则输出字符串“毕业,再见!”。
参考代码如下: 



1#E3-26.py

2#去掉字符并输出

3for k in "BIYE":

4if k=="I":

5continue

6print(k,end="-")

7else:

8print("毕业,再见!")






程序运行结果如下: 



B-Y-E-毕业,再见!






扩展: 若用break代替例326中的continue,会有什么样的结果?
针对这一问题,改写程序如下所示: 



1#E3-26扩展1.py

2#去掉字符并输出

3for k in "BIYE":

4if k=="I":

5break

6print(k,end="-")

7else:

8print("毕业,再见!")






程序运行结果如下: 



B-






分析: 如果循环是由break语句结束的,则else部分的语句不执行,所以程序的运行结果中没有输出字符串“毕业,再见!”
扩展: 若用pass代替例326中的continue,会有什么样结果?
针对这一问题,改写程序如下所示: 



1#E3-26扩展2.py

2#去掉字符并输出

3for k in "BIYE":

4if k=="I":

5pass

6print(k,end="-")

7else:

8print("毕业,再见!")






程序运行结果如下: 



B-I-Y-E-毕业,再见!






分析: pass语句是一个空语句,在本程序中去掉if分支部分也不影响最后的结果; 由于没有break语句,else部分也会正常执行。
3.5嵌 套 程 序
无论是分支结构还是循环结构,都允许嵌套。嵌套就是分支内还有分支,循环内还有循环或者分支内有循环,循环内有分支等。在设计嵌套程序时,要特别注意内层结构和外层结构之间的嵌套关系,以及各语句放置的位置。要保证外层结构完全包含内层结构,不允许出现交叉。
【例327】输入一个数,如果该数是偶数,则绘制一个圆形(半径100,红色填充),否则逆时针绘制一个正方形(边长200,黄色填充)。
参考代码如下: 



1#E3-27.py

2#根据输入绘制不同形状

3from turtle import *

4

5x=eval(input("输入一个数: "))

6begin_fill()

7if x%2==0:

8fillcolor('red')

9circle(200)

10else:

11fillcolor("yellow")

12for i in range(4):

13fd(200)

14left(90)

15end_fill()






当输入一个偶数时,程序会绘制一个红色圆形; 当输入一个奇数时,程序会绘制一个黄色正方形。这段程序用双路分支结构判断输入数据的奇偶,if部分的程序用于绘制圆形,else部分用于绘制正方形。总体来讲,该段程序是一个嵌套程序,具体位置是在双路分支结构的else部分嵌套了一个for循环结构。
对于while循环,如果<条件表达式>的值恒为True,我们称这种循环结构为恒真循环,也称为无穷循环。为了保证恒真循环不是死循环,通常会在恒真循环内部嵌套带有if分支结构的break语句。
【例328】用恒真循环改写例324。
参考代码如下: 



1#E3-28.py

2#恒真循环改写例3-24

3s=0

4while True:

5x=eval(input("请输入一个正整数:"))

6if x<=0:

7break

8s=s+x    

9print("s=",s)






循环内嵌套循环也是常用的一种嵌套程序模式。这种嵌套模式需要特别注意内层循环和外层循环之间变量的关系。
【例329】利用循环输出九九乘法表。
参考代码如下: 



1#E3-29.py

2#九九乘法表

3for i in range(1,10,1):

4for j in range(1,i+1,1):

5print('{}*{}={:<2d}'.format(i,j,i*j),end=' ')

6print('')






程序运行结果如下: 



1*1=1

2*1=22*2=4

3*1=33*2=63*3=9

4*1=44*2=84*3=124*4=16

5*1=55*2=105*3=155*4=205*5=25

6*1=66*2=126*3=186*4=246*5=306*6=36

7*1=77*2=147*3=217*4=287*5=357*6=427*7=49

8*1=88*2=168*3=248*4=328*5=408*6=488*7=568*8=64

9*1=99*2=189*3=279*4=369*5=459*6=549*7=639*8=729*9=81








图312由*号组成的

图形

【例330】利用循环输出由*号组成的图形,如图312所示。
参考代码如下: 



1#E3-30.py

2#输出图形

3for i in range(4):








4for j in range(3-i):

5print(' ',end='')

6for j in range(2*i+1):

7print("*",end='')

8print('')






程序运行结果如下: 



*

***

*****

*******






3.6程序的异常处理
对于程序设计者而言,编写程序过程中可能会出现一些错误,导致程序出错或终止。通常错误可以分为如下三类。
(1) 运行时错误
在运行时产生的错误称为异常,如果在程序中引发了未经处理的异常,程序就会由于异常而终止运行。例如,除数为0、名字错误、磁盘空间不足等。
(2) 语法错误
语法错误也称编译错误或解析错误,是指违背语法规则而引发的错误。通常情况下,Python解释器会指出错误的位置和类型。例如,函数括号的重复或缺失,分支或循环结构中冒号的缺失等。
(3) 逻辑错误
逻辑错误不会导致解释器报错,但执行结果不正确。其主要原因是代码的逻辑错误导致。例如: 算术表达式中的“+”错误地写成了“-”号,表达式“i+=1”错误地写成了“i+=2”,或者语句先后顺序颠倒等问题造成的逻辑错误。
在发生异常时,Python解释器会返回异常信息。例如下面这段程序: 
【例331】异常发生举例。



1#E3-31.py

2#异常发生举例

3x=3

4y=int(input("输入一个整数: "))

5print(x+y)






程序运行结果如下: 



Traceback (most recent call last):

File "D:/ Eg /E-31.py", line 4, in <module>

y=int(input("输入一个整数: "))

ValueError: invalid literal for int() with base 10: '3.1'






该结果出现了异常,这是由于输入的数据是一个浮点数而非整数,int函数在对输入数据进行转换时发生了异常。
异常运行结果中的信息说明如下: 
 Traceback: 异常回溯标记。
 "D:/pycharmproject/py1": 异常文件路径。根据文件保存的位置不同而不同。
 line 2: 异常产生的代码行数。根据异常产生的位置不同,“line”后的数字也会不同。
 ValueError: 异常类型。根据异常发生的情况进行分类,常见异常类型有很多种,如ZeroDivisionError、NameError等。
 invalid literal for int() with base 10: '3.1': 异常内容提示。不同的异常情况会有不同的提示。
Python语言采用结构化的异常处理机制捕获和处理异常。异常处理的语法格式如下所示。

try:

<语句块0>

except[ <异常类型1>]:

<语句块1>

[except[ <异常类型2>]:

<语句块2>

……

except[ <异常类型n>]:

<语句块n>]

[else:

<语句块n+1>]

[finally:

<语句块n+2>]

其中: 
 异常处理以try开头。
 <语句块0>中的语句是可能发生异常的语句,若有异常,则执行到发生异常前。
 <异常类型1>/<语句块1>: 将程序运行时产生的异常类型与<异常类型1>进行比对,若一致则执行对应的<语句块1>。若<异常类型1>缺省,则所有情况的异常都可以在对应的<语句块1>中执行。其余异常类型和语句块的处理方式与<异常类型1>/<语句块1>部分的处理方式相同。
 else: 不发生异常时执行<语句块n+1>。
 finally: 发不发生异常都执行<语句块n+2>。
最简单的捕捉和处理异常的形式是采用一个tryexcept结构来完成。
【例332】利用简单的tryexcept结构处理例331中的异常。



1#E3-32.py

2#简单异常处理举例

3x=3

4try:

5y=int(input("输入一个整数: "))








6print(x+y)

7except ValueError:

8print("输入错误,请输入一个整数")






输入数值3.1,程序运行结果如下: 



输入一个整数: 3.1

输入错误,请输入一个整数






输入数值5,程序运行结果如下: 



输入一个整数: 5

8






常见异常类型如表31所示。


表31常见异常类型



异 常 类 型描述

AttributeError调用未知对象属性时引发的异常
EOFError发现一个不期望的文件或输入结束时引发的异常
IndexError使用序列中不存在的索引时引发的异常
IOErrorI/O操作引发的异常
KeyError使用字典中不存在的关键字引发的异常
NameError使用不存在的变量名引发的异常
ValueError参数错误引发的异常
ZeroDivisionError除数为0引发的异常

【例333】下面两段程序中,假设有可能出现两种异常: 一种是由于输入异常导致,另一种是由于除数为0导致。输入异常将在程序运行时输入非数值型数据产生,除数为0异常是在程序运行时输入数值0产生的。对比以下两种处理方法,分析程序运行结果及原因。



1#E3-33方法一.py

2#方法一

3x=2

4try:

5y=eval(input("y="))

6z=x/y

7print(z)

8except:

9print('除数为0')









1#E3-33方法二.py

2#方法二

3x=2

4try:








5y=eval(input("y="))

6z=x/y

7print(z)

8except ZeroDivisionError:

9print('除数为0')






解析: “方法一”和“方法二”的不同点就在于except后的异常类型是否标注。针对两种不同的异常类型,分别进行分析。
(1) 除数为0产生的异常
在输入时,若y的值输入为0,则应产生除数为0的异常。
“方法一”运行时,输入y的值为0,程序运行结果如下: 



y=0

除数为0






“方法二”运行时,输入y的值为0,程序运行结果如下: 



y=0

除数为0






(2) 输入错误产生的异常
在输入时,若y的值输入为非数值类型数据,则应产生异常。
“方法一”运行时,输入y的值为字母k,程序运行结果如下: 



y=k

除数为0






“方法二”运行时,同样输入y的值为字母k,程序运行结果如下: 



y=k

Traceback (most recent call last):

File "D: /Eg/E-33方法二.py", line 5, in <module>

y=eval(input("y="))

File "<string>", line 1, in <module>

NameError: name 'k' is not defined






我们看到,两种方法中输入y的值都是非数值型数据k,但结果却不相同。“方法一”中并没有解决输入的y值非数值的问题,而是仍然认为输入的除数为0,这显然是错误的。导致这一错误的原因是except后的异常类型是否给出。如果没有明确给出异常类型,则认为程序中产生的所有异常都可以在该except后的语句中被处理。因此虽然输入非数值型数据导致的异常并不应该打印“除数为0”,但解释器也错误地认为可以用这种方法来解决。而“方法二”则明确了该except语句能够解决的异常类型为ZeroDivisionError,所以这部分语句只处理除数为0的异常,而输入非数值型数据异常发生时,并没有将该异常捕获,而是将该异常抛出。
【例334】改写例333,使其能够正确处理两种类型的异常。
参考代码如下: 



1#E3-34.py

2#改进例3-33

3x=2

4try:

5y=eval(input("y="))

6z=x/y

7print(z)

8except NameError:

9print("输入错误,请输入一个数")

10except ZeroDivisionError:

11print('除数为0')

12z=x/(y+0.0001)

13print(z)

14else:    

15print("没有异常发生")

16finally:

17print("计算完成")






运行程序,为y的值输入0,程序运行结果如下: 



y=0

除数为0

20000.0

计算完成






运行程序,为y的值输入k,程序运行结果如下: 



y=k

输入错误,请输入一个数

计算完成






运行程序,为y的值输入3,程序运行结果如下: 



y=3

0.6666666666666666

没有异常发生

计算完成






3.7random库
random库是Python的一个标准库,包含多种生成随机数的函数。random库中的大部分函数都基于random()函数,该函数使用梅森旋转算法(Mersenne twister)生成随机数。梅森旋转算法是一个伪随机数发生算法,所以由random()函数和基于random()函数生成随机数的函数所生成的随机数都是伪随机数。
使用random库的功能前,需要先导入random库。
random库包含两类函数,分别是基本随机函数和扩展随机函数,如表32、表33所示。


表32random库基本随机函数



函数功 能 描 述表达式实例&实例结果

seed(a)用于初始化随机数种子,a缺省时默认为当前系统时间。只要确定了随机数种子,每一次产生的随机序列都是确定的实例: random.seed(5)

结果: 无显示结果
random()用于生成一个[0.0,1.0]之间的随机小数
实例: random.random()

结果: 0.6229016948897019

(此结果前提是执行语句random.seed(5))



表33random库扩展随机函数



函数功 能 描 述表达式实例&实例结果

uniform(a,b)用于生成一个[a,b]之间的随机小数
实例: random.uniform(3,7)

结果: 5.967147957042918(此结果随机,在[3,7]中选取任一小数)

randint(a,b)用于生成一个[a,b]之间的整数,要求a≤b

实例: random.randint(3,7)

结果: 6(此结果随机,在[3,7]中选取任一整数)
实例: random.randint(7,3) 

结果: ValueError

randrange([start,]stop[,step])用于生成一个[start,stop)之间的以step为步长的随机整数。m缺省时的默认值为0,step缺省时的默认值为1。要求start≤stop,且有参数step时,start不可以缺省

实例: random.randrange(1,10,2)

结果: 3(此结果随机,在[1,10)中选取步长为2的任一整数)
实例: random.randrange(10,2)

结果: ValueError
实例: random.randrange(10)

结果: 8(此结果随机,在[0,10)中选取任一整数)

randchoice(seq)用于从序列seq中随机选取一个元素

实例: random.choice([3,7,8,11,23])

结果: 7(此结果随机,在给定参数列表中选取任一元素)
实例: random.choice('Python')

结果: 't'(此结果随机,范围是'Python'中的任一字母)
实例: random.choice(['Python','VC','VB','Java'])

结果: 'VC'(此结果随机,在给定参数列表中选取任一元素)

shuffle(seq)用于将序列seq的顺序重新随机排列,并返回重新排列后的结果
实例: s=[3,7,8,11,23]

random.shuffle(s)

print(s)

结果: [3, 8, 23, 11, 7](此结果随机)

续表



函数功 能 描 述表达式实例&实例结果

sample(seq,k)用于从序列seq中随机选取k个元素组成新的序列
实例: random.sample([3,7,8,11,23],3)

结果: [11, 8, 23](此结果随机)
getrandbits(k)用于生成一个k比特长的随机整数
实例: random.getrandbits(6)

结果: 38(对应的二进制数为100110,6比特长。此结果随机)

【例335】班级举行抽奖活动,参与抽奖活动的学生有10名,分别是王东明、张帅阳、郝晴、潘盼盼、魏晓娟、孙清成、于胜、李丹、王文菲、高爽。利用随机函数抽取3名幸运之星。
参考代码如下: 



1#E3-35.py

2#抽取幸运之星

3import random

4namelist=['王东明','张帅阳','郝晴','潘盼盼','魏晓娟','孙清成','于胜','李丹','王文菲','高爽']

5

6print(random.sample(namelist,3))






程序运行的一个随机结果如下: 



['李丹', '王文菲', '魏晓娟']






【例336】猜数字游戏: 程序随机生成1~5的整数,参与游戏者输入猜想的数值,若猜中,则输出“猜中啦”; 否则输出“不对哦”。
参考代码如下: 



1#E3-36.py

2#猜数字游戏

3import random

4num=random.randint(1,5)

5guess=int(input('请输入1~5的整数: '))

6print('答案是{},您猜的数字是{}'.format(num,guess))

7if guess==num:

8print('猜对啦')

9else:

10print('不对哦')






按要求输入一个整数,程序会生成一个待匹配的随机数,程序运行结果如下: 



请输入1~5的整数: 3

答案是2,您猜的数字是3

不对哦






【例337】猜数字游戏升级版: 程序随机生成1~5的整数,参与游戏者输入猜想的数,若猜中,则输出“猜中啦”; 否则输出“不对哦”。循环该过程,直到用户不想玩为止。
参考代码如下: 



1#E3-37.py

2#循环猜数字游戏

3import random

4while True:

5num=random.randint(1,5)

6guess=int(input('请输入1~5的整数: '))

7print('答案是{},您猜的数字是{}'.format(num,guess))

8if guess==num:

9print('猜对啦')

10else:

11print('不对哦')

12yn=input('接着玩按y --->')

13if yn!='y'and yn!='Y':

14break






这段代码将例336的程序嵌套到一个while恒真循环中,并添加了用户意愿交互,提升用户体验。根据提示依次输入3、y、5、n,程序运行结果如下: 



请输入1~5的整数: 3

答案是1,您猜的数字是3

不对哦

接着玩按y --->y

请输入1~5的整数: 5

答案是5,您猜的数字是5

猜对啦

接着玩按y --->n






上 机 练 习
【题目1】输入圆柱体的高(H)和底面半径(R),编程求解并输出圆柱体的体积(V)。
【题目2】编程求解一元二次方程ax2+bx+c=0的两个根,要求输入a、b、c的值分别为3、4、1。


图313用turtle绘制

三原色圆

【题目3】用turtle绘制如下填充了三种颜色的圆形,圆的半径为200,填充颜色分别为红色、黄色、蓝色,如图313所示。
提示: 参照例34编写代码,并尝试完成如下问题: 
(1) 更换本题中的颜色,并填充。
(2) 尝试在圆中填充6种或更多种的颜色。
【题目4】输入一个数,如果该数大于0,则输出其平方根。
【题目5】输入一个字符,如果该字符是字母,则输出“用户输入的是字母”。
【题目6】输入一个数,如果该数能被3或7整除,则输出“该数能同时被3和7整除”。
【题目7】某运输公司的收费按照用户运送货物的路程进行计算,其运费折扣标准如表34所示。请编写程序: 在输入路程后,计算运输公司的运费并输出。


表34运费折扣标准



路程/km运费的折扣路程/km运费的折扣

s<250没有折扣1000≤s<20008%
250≤s<5002%2000≤s<300010%
500≤s<10005%s≥300015%

【题目8】输入三个数,找出其中最大数。
提示: 首先,输入三个数并分别保存到变量x,y,z中。先假定第一个数是最大数,即将x赋值给max变量,然后将max分别和y,z比较,两次比较后,max的值即为x,y,z中的最大数。
要求: 用嵌套的if结构实现。
【题目9】计算1~100所有偶数的和。
【题目10】计算n!


图314用turtle绘制

正方形

【题目11】利用for循环逆时针绘制一个正方形,填充颜色为黄色,如图314所示。
【题目12】从键盘输入若干个数,求所有正数的平均值。当输入0或负数时,程序结束。
提示: 参照例324。
【题目13】输入一个数n,绘制n个如图315所示的圆,半径分别为1×50、2×50、…、n×50。
要求: 分别用for和while两种循环结构完成。
【题目14】利用for循环去掉字符串"ABCABCABC"中所有字母"C",并输出。
【题目15】用while改写题目14。
【题目16】利用循环输出如图316所示图形。



图315用turtle绘制多个圆




图316由*号组成的图形



【题目17】请用异常处理改造如下程序,使其能够接收并处理用户的任何输入。



1a=input("输入一个字符数据: ")

2n=int(input("输入一个整数: "))








3for i in range(n):

4print("序号为: {}{}".format(a,i))






【题目18】随机产生一个1~10的整数。玩家竞猜,对玩家猜的数字进行判断,根据不同情况分别输出“猜对了”,“小了”,“大了”。
【题目19】用随机函数模拟扑克牌洗牌。
习题
【选择题】
1. 关于Python程序文件的描述,错误的是()。

A. Python程序文件的扩展名为.py
B. Python文件一般包括模块导入、函数定义和程序主体等部分
C. Python文件中必须包含注释部分
D. IDLE中运行程序文件的快捷键是F5
2. 关于缩进,以下说法中错误的是()。
A. Python程序对缩进有着严格的要求
B. Python可以使用Tab键缩进一级
C. Python可以使用4个空格缩进一级
D. Python可以使用Insert键缩进一级
3. 关于下面程序,说法正确的是()。



1import turtle

2x=eval(input("输入一个整数:"))

3if x%2==0:

4turtle. color("blue")

5else:

6turtle. color("red")

7turtle.pensize(5)

8turtle.begin_fill()

9turtle.circle(100)

10turtle.end_fill()






A. 这段代码的结果是绘制一个圆环
B. 绘制图形的线条颜色是黑色的
C. 绘制图形的填充颜色是红色或蓝色
D. 绘制图形的半径是110
4. 关于Python的分支结构,以下说法中正确的是()。
A. 分支结构分为单路分支、双路分支和多路分支
B. 不能用双路分支语句改写多路分支语句
C. 在多路分支结构中,只要条件满足,所有分支下的语句都会被执行
D. 分支结构中不能嵌套其他分支结构
5. 对于语句y="Yes" if guess==5 else "No",描述错误的是()。
A. 如果guess的值为5,则y的值是"Yes"
B. 如果guess的值为15,则y的值是"No"
C. 如果guess的值为5,则y的值是"No"
D. 如果guess的值为-5,则y的值是"No"
6. 下面程序的运行结果是()。



1sum = 0

2for i in range(2,101):

3if i % 2 == 0:

4sum+= i

5else:

6sum -= i

7print(sum)






A. 49
B. 50
C. 51
D. 52
7. 下面程序的运行结果是()。



1s = 'LNDX'

2for i in s:

3if i == 'N':

4break

5print(i)






A. LNDX




B. L

N

D

X
C. LN




D. L




8. 关于下面程序,说法正确的是()。



1num = 6

2

3while True:

4guess_num = int(input("guess_num:"))

5if guess_num == num:

6print("Right")

7break

8else:

9print("Wrong")






A. 该循环是一个死循环
B. 当输入6时循环结束
C. 当输入“Right”时循环结束
D. 当输入“Wrong”时循环结束
9. 以下说法中错误的是()。
A. break语句的作用是跳出循环
B. continue语句的作用是结束本次循环
C. pass语句的作用是忽略本次循环
D. 循环语句可以和break、continue或pass语句一起使用
10. 关于random库,以下说法错误的是()。
A. random库中的大部分函数都基于random()函数
B. random库是Python的一个第三方库
C. shuffle()用于将序列的顺序重新随机排列
D. sample()用于从序列中随机选取指定多个元素组成新的序列
【填空题】
1. 指每一行代码开始前的空白区域,用来表示代码之间的包含和层次关系。
2. 分支结构分为结构、结构和结构。
3. 表达式'A' if 3>6 else ('B' if 5>2 else 'C')的值为。
4. 在循环语句中,语句的作用是跳出循环。
5. 执行循环语句for i in range(2,8,2):print(i),循环体执行的次数是。
6. 语句是空语句,不做任何事情,一般只用作占位。
7. 就是分支内还有分支,循环内还有循环或者分支内有循环,循环内有分支等。
8. 程序执行时,如果除数为0,会导致的异常类型为。
9. random库包含两类函数,分别是函数和函数。
10. random库中,函数的作用是初始化随机种子。
【判断题】
1. Python代码的注释只能使用#号。()
2. 程序的三种基本结构为顺序结构、分支结构和循环结构。()
3. 多路分支可以用双路分支改写。()
4. 如果仅仅是用于控制循环次数,那么使用for i in range(20)和for i in range(20, 40)的作用是等价的。()
5. 在循环中continue语句的作用是跳出当前循环。()
6. 对于带有else子句的循环语句,如果是因为循环条件表达式不成立而自然结束循环,则执行else子句中的代码。()
7. 程序中异常处理结构在大多数情况下是没必要的。()
8. 在异常处理结构中,不论是否发生异常,finally子句中的代码总是会执行的。()
9. 在try…except…else结构中,如果try中语句引发了异常,则会执行else子句中的代码。()
10. Python标准库random的方法randint(m,n)用来生成一个[m,n]区间上的随机整数。()
【简答题】
1. 简述Python程序的基本构成。
2. <条件表达式>的值在什么情况下为False?
3. 简述range()函数三个参数的作用。
4. 简述break、continue和pass的作用。
5. 简述异常的概念。