第3章
Python控制语句




对于Python程序中的执行语句,默认是按照书写顺序依次执行的,称这样的语句是顺序结构的。但是,仅有顺序结构还不够,因为有时需要根据特定的情况有选择地执行某些语句,这时就需要一种选择结构的语句。另外,有时还可以在给定条件下重复执行某些语句,这时称这些语句是循环结构的。有了这3种基本的程序结构,就能够构建任意复杂的程序了。



视频讲解



3.1选 择 结 构
3种基本程序结构中的选择结构可用if语句、if…else语句和if…elif…else语句实现。
3.1.1if语句
Python中if语句的功能跟其他语言非常相似,都是用来判定给出的条件是否满足,然后根据判断的结果(即真或假)决定是否执行给出的操作。if语句是一种单选结构,它选择的是做或不做。它由3部分组成,即关键字if本身、测试条件真假的表达式(简称为条件表达式)和表达式结果为真(即表达式的值为非零)时要执行的代码。if语句的语法形式如下: 


if 表达式: 
语句1



图31if语句的流程


if语句的流程如图31所示。

if语句的表达式用于判断条件,可以用>(大于)、<(小于)、==(等于)、>=(大于或等于)、<=(小于或等于)来表示其关系。
现在用一个示例程序来演示一下if语句的用法。程序很简单,只要用户输入一个整数,如果这个数大于6,那么就输出一行字符串; 否则直接退出程序。代码如下: 



#比较输入的整数是否大于6

a = input("请输入一个整数: ")#取得一个字符串

a = int(a)#将字符串转换为整数

if a > 6:

print( a, "大于6")





通常,每个程序都会有输入和输出,这样可以与用户进行交互。用户输入一些信息,程序对用户输入的内容进行一些适当的操作,然后输出用户想要的结果。Python可以用input进行输入,用print进行输出,这些都是简单的控制台输入与输出操作,复杂的操作有处理文件等。

第
3
章
Python控制语句

Python程序设计——从基础开发到数据分析(第2版)微课版
3.1.2if…else语句
if语句是一种单选结构,也就是说,如果条件为真(即表达式的值为非零),那么执行指定的操作; 否则就会跳过该操作。if…else语句是一种双选结构,是在两组备选动作中选择哪个的问题。if…else语句由5部分组成,即关键字if、测试条件真假的表达式、表达式结果为真(即表达式的值为非零)时要执行的代码,以及关键字else和表达式结果为假(即表达式的值为零)时要执行的代码。if…else语句的语法形式如下: 

if 表达式: 
语句1
else: 
语句2



图32if…else语句的流程


if…else语句的流程如图32所示。

下面对上面的示例程序进行修改,以演示if…else语句的使用方法。程序很简单,只要用户输入一个整数,如果这个数大于6,那么就输出一行信息,指出输入的数大于6; 否则输出另一行字符串,指出输入的数小于或等于6。代码如下: 



a = input("请输入一个整数: ")#取得一个字符串

a = int(a)#将字符串转换为整数

if a > 6:

print( a, "大于6")

else:

print( a, "小于或等于6")




再例如输入一个年份,判断是否为闰年。闰年的年份必须满足以下两个条件之一: 
(1) 能被4整除,但不能被100整除的年份。
(2) 能被400整除的年份。
用变量year表示年份,判断year是否满足闰年的条件如下。
条件(1)的逻辑表达式是: year%4==0 and year%100!=0。
条件(2)的逻辑表达式是: year%400==0。
两者取“或”,即得到判断闰年的逻辑表达式如下: 
(year%4==0 and year%100!=0) or year%400==0
程序如下: 



year = int(input('输入年份:'))#input()获取的是字符串,所以需要转换成整型

ifyear%4==0 and year%100!=0 or year%400==0:#注意运算符的优先级

print(year, "是闰年")







else:

print(year, "不是闰年")






【例31】任意输入3个数字,按从小到大的顺序输出。
分析: 先将x与y比较,把较小者放入x中,较大者放入y中; 再将x与z比较,把较小者放入x中,较大者放入z中,此时x为三者中的最小者; 最后将y与z比较,把较小者放入y中,较大者放入z中,此时x、y、z已按从小到大的顺序排列。代码如下:



x = input('x=')#输入x

y = input('y=')#输入y

z = input('z=')	#输入z

if x > y:

x, y = y, x		#x和y互换

if x > z:

x, z = z, x#x和z互换

if y > z:

y, z = z, y		#y和z互换

print(x, y, z)




假如x、y、z分别输入1、4、3,以上代码的输出结果如下:



x=1↙(输入x的值,↙表示回车)

y=4↙(输入y的值)

z=3↙(输入z的值)

1 3 4




其中“x, y = y, x”这种语句是同时赋值,将赋值号右侧的表达式依次赋给左侧的变量。例如,“x, y = 1, 4”就相当于“x=1; y=4”的效果,可见Python语法多么简洁。

3.1.3if…elif…else语句
有时候需要在多组动作中选择一组执行,这时就会用到多选结构,对于Python语言来说就是if…elif…else语句。该语句可以利用一系列条件表达式进行检查,并在某个表达式为真的情况下执行相应的代码。需要注意的是,虽然if…elif…else语句的备选动作较多,但是有且只有一组动作被执行。该语句的语法形式如下: 

if 表达式1: 
语句1
elif 表达式2: 
语句2
︙
elif 表达式n: 
语句n
else: 
语句n+1


注意,最后一个elif子句之后的else子句没有进行条件判断,它实际上处理跟前面所有条件都不匹配的情况,所以else子句必须放在最后。if…elif…else语句的流程如图33所示。


图33if…elif…else语句的流程


下面继续对上面的示例程序进行修改,以演示if…elif…else语句的使用方法。用户输入一个整数,如果这个数大于6,那么就输出一行信息,指出输入的数大于6; 如果这个数小于6,则输出另一行字符串,指出输入的数小于6; 否则指出输入的数等于6。具体的代码如下: 



a = input("请输入一个整数: ")#取得一个字符串

a = int(a)#将字符串转换为整数

if a > 6:

print( a, "大于6")

elif a==6:

print( a, "等于6")

else: 

print( a, "小于6")





【例32】输入学生的成绩score,按分数输出其等级,其中score≥90为优,90>score≥80为良,80>score≥70为中等,70>score≥60为及格,score<60为不及格。
代码如下:



score=int(input("请输入成绩")) #int()转换字符串为整型

if score >= 90: 

print("优")

elif  score >= 80: 

print("良") 

elif  score >= 70:

print("中")







elif  score >= 60: 

print("及格")

else:

print("不及格")




说明: 在3种选择语句中,条件表达式都是必不可少的组成部分。当条件表达式的值为零时,表示条件为假; 当条件表达式的值为非零时,表示条件为真。那么哪些表达式可以作为条件表达式呢?基本上,最常用的是关系表达式和逻辑表达式。例如: 



if  a == x  and  b == y:

print("a = x, b = y")





除此之外,条件表达式还可以是任何数值类型表达式,甚至字符串也可以。例如: 



if  'a':   #'abc':也可以

print("a = x, b = y")





另外,C语言是用花括号{}来区分语句体的,而Python的语句体是用缩进形式来表示的,如果缩进不正确,则会导致逻辑错误。
3.1.4pass语句
Python提供了一个关键字pass,类似于空语句,可以用在类和函数的定义中或者选择结构中。当暂时没有确定如何实现功能,或者为以后的软件升级预留空间,又或者实现其他类型功能时,可以使用该关键字来“占位”。例如下面的代码是合法的: 



if a<b:

pass#什么操作也不做

else:

z=a

class A:#类的定义

pass

def demo():#函数的定义

pass





3.2循 环 结 构
程序在一般情况下是按顺序执行的。编程语言提供了各种控制结构,允许更复杂的执行路径。循环语句允许执行一个语句或语句组多次,Python提供了while循环(在Python中没有do…while循环)和for循环。



视频讲解



3.2.1while语句


图34while语句的流程


在Python编程中,while语句用于循环执行程序,即在某个条件下循环执行某段程序,以便处理需要重复处理的相同任务。while语句的流程如图34所示。其基本形式为: 

while 判断条件: 
执行语句

判断条件可以是任何表达式,任何非零或非空(null)的值均为真。当判断条件为假时循环结束。执行语句可以是单个语句或语句块。注意程序中的冒号和缩进。例如: 



count = 0

while count < 9:

print('The count is:', count)

count = count + 1

print("Good bye!")





以上代码的输出结果如下: 



The count is: 0

The count is: 1

The count is: 2

The count is: 3

The count is: 4

The count is: 5

The count is: 6

The count is: 7

The count is: 8

Good bye!





此外,while语句中的判断条件还可以是一个常值,表示循环必定成立。例如: 



count = 0

while 1:#判断条件是个常值1

print ('The count is:', count)

count = count + 1

print ("Good bye!" )





这样就形成无限循环,可以借助后面学习的break语句结束循环。
【例33】输入两个正整数,求它们的最大公约数。
分析: 求最大公约数可以用“辗转相除法”,方法如下。
(1) 比较两个数m和n,并使m大于n。
(2) 将m作为被除数,n作为除数,相除后余数为r。
(3) 循环判断r,若r=0,则n为最大公约数,结束循环。若r≠0,执行步骤m←n,n←r; 将m作为被除数,n作为除数,相除后余数为r。
代码如下:



num1 = int(input("输入第一个数字: "))#用户输入两个数字

num2 = int(input("输入第二个数字: "))

m = num1

n = num2

if m < n:#m和n交换值

t = m

m = n

n = t

r = m % n

while  r!=0:

m = n

n = r

r = m % n

print(num1,"和", num2,"的最大公约数为", n)





以上代码的执行与输出结果如下: 



输入第一个数字: 36

输入第二个数字: 48

36 和 48 的最大公约数为 12







视频讲解



3.2.2for语句
for语句可以遍历任何序列的项目,例如一个列表、元组或者一个字符串。
1. for循环的语法
for循环的语法格式如下: 

for循环索引值 in 序列:
循环体

for语句的执行过程是: 每次循环从序列中依次取出一个元素,存放于循环变量中,该元素提供给循环体内的语句使用,直到所有元素取完为止,则结束循环。例如: 
for循环把字符串中的字符遍历出来。



for letter in 'Python': #第一个实例

print( '当前字母:', letter )





以上实例的输出结果如下:



当前字母: P

当前字母: y

当前字母: t

当前字母: h

当前字母: o

当前字母: n





for循环把列表中的元素遍历出来。



fruits = ['banana', 'apple',  'mango']

for fruit in fruits:#第二个实例

print( '元素:', fruit)

print( "Good bye!" )





此时会依次打印fruits中的每个元素。以上实例的输出结果如下:



元素: banana

元素: apple

元素: mango

Good bye!





【例34】计算1~10的整数之和,可以用一个sum变量做累加。
代码如下:



sum = 0

for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:

sum = sum + x

print(sum)





如果要计算1~100的整数之和,从1写到100有点困难,幸好Python提供了一个range()内置函数,可以生成一个整数序列,再通过list()函数可以转换为list。
例如,range(0, 5)或range(5)生成的序列是从0开始到小于5的整数,不包括5。实例如下: 



>>> list(range(5))

[0, 1, 2, 3, 4]





range(1, 101)就可以生成1~100的整数序列。计算1~100的整数之和的代码如下: 



sum = 0

for x in range(1,101):

sum = sum + x

print(sum)





请读者自行运行上述代码,查看结果是不是5050。
2. 通过索引循环
对于一个列表,另外一种执行循环的遍历方式是通过索引(元素的下标)。实例如下: 



fruits = ['banana', 'apple',  'mango']

for i in range(len(fruits)):

print( '当前水果:', fruits[i] )

print("Good bye!")





以上实例的输出结果如下: 



当前水果 : banana

当前水果 : apple

当前水果 : mango

Good bye!





以上实例使用了内置函数len()和range()。函数len()返回列表的长度,即元素的个数,通过索引i访问每个元素fruits[i]。
字典提供了内置函数keys()、values()和items(),可以获取字典中所有的“键”“值”和“键-值”对。返回值是一个可迭代对象。
例如现有一个字典存放学生的学号和3门课程的成绩,以下代码返回每个学生的学号及其平均分。



dictScore={"101":[67,88,45],"102":[97,68,85],"103":[98,97,95]

,"104":[67,48,45],"105":[82,58,75],"106":[96,49,65]}

for xuehao in dictScore.keys():#输出每个学生的学号

print(xuehao)

for key,value in dictScore.items():#输出每个学生的平均分

print(key,sum(value)/3)




3.2.3continue语句和break语句
continue语句的作用是终止当前循环,并忽略continue之后的语句,然后回到循环的顶端,提前进入下一次循环。
break语句在while循环和for循环中都可以使用,一般放在if选择结构中,一旦break语句被执行,将使得整个循环提前结束。
除非break语句让代码更简单或更清晰,否则不要轻易使用。
【例35】continue和break用法示例。
代码如下:



#continue 和 break 用法

i = 1

while i < 10:   

i += 1

if i%2 > 0: #非双数时跳过输出

continue

print(i)         #输出双数2、4、6、8、10

i = 1

while 1:             #循环条件为1必定成立

print(i)         #输出1~10

i += 1

if i > 10:         #当i大于10时跳出循环

break





3.2.4循环嵌套
Python语言允许在一个循环体内嵌入另一个循环,例如可以在while循环中嵌入for循环,也可以在for循环中嵌入while循环。嵌套层次一般不超过3层,以保证程序的可读性。
注意: 
(1) 在循环嵌套时,外层循环和内层循环之间是包含关系,即内层循环必须被完全包含在外层循环中。
(2) 当程序中出现循环嵌套时,程序每执行一次外层循环,其内层循环必须在循环所有的次数(即内层循环结束)后才能进入外层循环的下一次循环。
【例36】打印九九乘法表。
代码如下:



for i in range(1,10):

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

print(i,'*',j,'=',i*j,'\t',end="")#end=""的作用是不换行

print("") #仅起换行作用




以上代码的输出结果如图35所示。


图35九九乘法表


【例37】使用嵌套循环输出2~100内的素数。
分析: 素数是除1和本身外不能被其他任何整数整除的整数。判断一个数m是否为素数,只要依次用2、3、4、…、m-1作为除数去除m,如果有一个能被整除,m就不是素数。代码如下:



m=int(input("请输入一个整数"))

j = 2

while j <= m-1:

if m%j==0: break		#退出循环

j = j + 1

if (j > m-1): 

print(m, "是素数")

else:

print(m, "不是素数")





应用上述代码,对于一个非素数而言,判断过程往往可以很快结束。例如,在判断30009时,因为该数能被3整除,所以只需判断j=2, 3两种情况。在判断一个素数,尤其是当该数较大时,例如判断30011,则要从j=2, 3, 4, …,一直判断到30010都不能被整除,才能得出其为素数的结论。实际上,只要从2判断到m,若m不能被其中的任何一个数整除,则m即为素数。



#找出100以内的所有素数

import math#导入math数学模块

m = 2

while m < 100:				#外层循环

j = 2

while j <= math.sqrt(m):#内层循环, math.sqrt()是求平方根函数

if m%j==0: break	#退出内层循环

j = j + 1

if (j > math.sqrt(m)): 

print(m, "是素数")

m = m + 1

print("Good bye!")




【例38】使用嵌套循环输出如图36所示的金字塔图案。

*

***

*****

*******

*********

***********

*************

***************



图36金字塔图案
分析: 观察图形包含8行,因此外层循环执行8次; 每行内容由两部分组成,即空格和星号。假设第1行的星号在第10列,则第i行空格的数量为10-i,星号的数量为2×i-1。代码如下:



for i in range(1,9):  #外层循环

for j in range(0,10-i):#循环输出每行的空格

print(" ", end="") 

for j in range(0,2*i-1):#循环输出每行的星号

print("*", end="")

print("")#仅起换行作用




另外也可以用如下代码实现: 



for i in range(1,9):

print(" "*(10-i), "*"*(2*i-1))#使用重复运算符输出每行的空格、星号




3.2.5列表生成式
列表生成式(List Comprehensions)是Python内置的一种极其强大的生成列表的表达式。如果要生成一个列表list [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9], 可以用 range(1, 10),代码如下:



>>> L= list(range(1, 10))#L是[1, 2, 3, 4, 5, 6, 7, 8, 9]




如果要生成[1*1, 2*2, 3*3, …, 10*10],可以使用如下循环: 



>>> L= []

>>>for x in range(1 , 10):

L.append(x*x)

>>> L

[1, 4, 9, 16, 25, 36, 49, 64, 81]




而使用列表生成式,可以用如下一行语句代替以上烦琐的循环来实现上面的操作: 



>>> [x*x for x in range(1 , 11)] 

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]




列表生成式的书写格式是把要生成的元素 x*x 放到前面,后面跟for循环。这样就可以把list创建出来。在for循环的后面还可以加上if判断。例如筛选出偶数的平方,代码如下: 



>>> [x*x for x in range(1 , 11) if x%2 == 0]

[4, 16, 36, 64, 100]




再如,把一个list列表中所有的字符串变成小写形式,代码如下: 



>>> L = ['Hello', 'World', 'IBM', 'Apple']

>>> [s.lower() for s in L]

['hello', 'world', 'ibm', 'apple']




当然,列表生成式也可以使用两层循环。例如,生成'ABC'和'XYZ'中字母的全部组合,代码如下: 



>>> print( [m + n for m in 'ABC' for n in 'XYZ'] ) 

['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']




再如,生成所有的扑克牌的列表,代码如下:



>>> color=["草花","方块","红桃","黑桃"]

>>> rank=["A","2","3","4","5","6","7","8","9","10","J","Q","K"]

>>> print( [m + n for m in color for n in rank]) 

['草花A', '草花2', '草花3', '草花4', '草花5', '草花6', '草花7', '草花8', '草花9', '草花10', '草花J', '草花Q', '草花K', '方块A', '方块2', '方块3', '方块4', '方块5', '方块6', '方块7', '方块8', '方块9', '方块10', '方块J', '方块Q', '方块K', '红桃A',  '红桃2', '红桃3', '红桃4', '红桃5', '红桃6', '红桃7', '红桃8', '红桃9', '红桃10', '红桃J', '红桃Q', '红桃K', '黑桃A', '黑桃2', '黑桃3', '黑桃4', '黑桃5', '黑桃6', '黑桃7', '黑桃8', '黑桃9', '黑桃10', '黑桃J', '黑桃Q', '黑桃K']





for循环其实可以同时使用两个甚至多个变量,例如字典的items()可以同时迭代key和value,代码如下: 



>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }#字典(dict)

>>>for  k, v  in d.items():

print(k, '键=', v, endl=';')




输出结果如下: 



y键= B; x 键= A; z 键= C;




因此,列表生成式也可以使用两个变量来生成list,代码如下: 



>>> d = {'x': 'A', 'y': 'B', 'z':'C' }

>>>[ k + '=' + v  for k, v in d.items()]

['y=B', 'x=A', 'z=C']




3.3常用算法及应用实例
3.3.1累加与累乘

累加与累乘是最常见的一类算法,这类算法就是在原有的基础上不断地加上或乘以一个新的数。例如求1+2+3+…+n、求n的阶乘、计算某个数列前n项的和,以及计算一个级数的近似值等。
【例39】求自然对数e的近似值。其近似公式如下: 
e=1+1/1!+1/2!+1/3!+…+1/n!

分析: 这是一个收敛级数,可以通过求其前n项和来实现近似计算。通常该类问题会给出一个计算误差,例如可设定当某项的值小于10-5时停止计算。
此题既涉及累加,也包含了累乘。程序如下: 



i = 1

p = 1

sum_e = 1

t=1/p

while t>0.00001:

p=p*i//计算i的阶乘

t=1/ p

sum_e=sum_e+t

i = i + 1;//为计算下一项做准备

print("自然对数e的近似值" ,sum_e);





运行结果如下: 



自然对数e的近似值 2.7182815255731922





3.3.2求最大数和最小数
求数据中的最大数和最小数的算法是类似的,可以采用“打擂”算法。以求最大数为例,可以先用其中的第一个数作为最大数,再用其与其他数逐个比较,并将找到的较大数替换为最大数。
【例310】求区间[100, 200]内10个随机整数中的最大数。
分析: 本题随机产生整数,所以引入random模块的随机数函数,其中random.randrange()可以从指定范围内获取一个随机数。例如,
random.randrange(6)从0~5中随机挑选一个整数,不包括数字6; 
random.randrange(2,6)从2~5中随机挑选一个整数,不包括数字6。代码如下:



import random

x=random.randrange(100,201) #产生[100, 200]的一个随机数x

maxn = x                      	#设定最大数

print(x,end=" ")

for i  in range(2, 11):

x=random.randrange(100,201)    #再产生[100, 200]的一个随机数x

print(x,end=" ")

if x > maxn:

maxn = x;            	 #若新产生的随机数大于最大数,则进行替换

print("最大数: ",maxn)





运行结果如下: 



185 173 112 159 116 168 111 107 190 188 最大数: 190





当然,在Python中求最大数有相应的函数max(序列)。例如: 



print("最大数: ",max([185,173, 112, 159, 116, 168, 111, 107, 190, 188])  #求序列的最大数





运行结果如下: 



最大数: 190





所以上例可以修改如下: 



import random

a = []#列表

for i  in range(1, 11):






x=random.randrange(100,201)#产生[100, 200]的一个随机数x

print(x,end=" ")

a.append(x)

print("最大数: ",max(a))





3.3.3枚举法
枚举法又称为穷举法,此算法将所有可能出现的情况一一进行测试,从中找出符合条件的所有结果。例如计算“百钱买百鸡”问题,又如列出满足x×y=100的所有组合等。
【例311】公鸡每只5元,母鸡每只3元,小鸡3只1元,现要求用100元钱买100只鸡,问公鸡、母鸡和小鸡各买几只?
分析: 设买公鸡x只,母鸡y只,小鸡z只。根据题意可列出以下方程组: 

x+y+z=100

5x+3y+z/3=100


由于两个方程式中有3个未知数,属于无法直接求解的不定方程,故可采用“枚举法”进行试根,即逐一测试各种可能的x、y、z组合,并输出符合条件者。代码如下:



for x in range(0, 100):

for y in range(0, 100):

z = 100-x-y

if z >= 0 and 5*x+3*y+z/3 == 100 :

print('公鸡%d只,母鸡%d只,小鸡%d只'%(x, y, z))





运行结果如下: 



公鸡0只,母鸡25只,小鸡75只

公鸡4只,母鸡18只,小鸡78只

公鸡8只,母鸡11只,小鸡81只

公鸡12只,母鸡4只,小鸡84只





【例312】输出“水仙花数”。
分析: 所谓水仙花数是指一个3位的十进制数,其各位数字的立方和等于该数本身。例如,153是水仙花数,因为153=13 + 53 + 33。代码如下:



for i in range(100,1000):

ge =  i % 10

shi = i // 10 % 10

bai = i // 100

if ge**3+shi**3+bai**3 == i:

print(i,end=" ")





运行结果如下: 



153 370 371 407





【例313】编写程序,输出由1、2、3、4这4个数字组成的每位数都不相同的所有3位数。
代码如下:



digits = (1, 2, 3, 4)

for i in digits:

for j in digits:

for k in digits:

if i!=j and j!=k and i!=k:

print(i*100+j*10+k)





3.3.4递推与迭代
1. 递推
利用递推算法或迭代算法可以将一个复杂的问题转换为一个简单的过程重复执行。这两种算法的共同特点是通过前一项的计算结果推出后一项; 不同点是递推算法不存在变量的自我更迭,而迭代算法在每次循环中用变量的新值取代其原值。
【例314】输出斐波那契(Fibonacci)数列的前20项。该数列的第1项和第2项为1,从第3项开始,每项均为其前面两项之和,即1,1,2,3,5,8,…。
分析: 设数列中相邻的3项分别为变量f1、f2和f3,则有如下递推算法。
① f1和f2的初值为1。
② 每次执行循环,用f1和f2产生后项,即f3 = f1 + f2。
③ 通过递推产生新的f1和f2,即f1 = f2,f2 = f3。
④ 如果未达到规定的循环次数,则返回步骤②; 否则停止计算。
代码如下:



f1=1

f2=1

print("1:", f1)

print("2:", f2)

for i  in range(3, 21):

f3 = f1 + f2#递推公式

print(i,":",f3)

f1 = f2

f2 = f3





说明: 解决递推问题必须具备两个条件,即初始条件和递推公式。本题的初始条件为f1=1和f2=1,递推公式为f3=f1+f2,f1=f2,f2=f3。
【例315】有一分数序列2/1,3/2,5/3,8/5,13/8,21/13,…,求出这个数列的前20项之和。
分析: 根据分子与分母的变化规律,可知后项分母为前项分子,后项分子为前项分子与分母之和。
代码如下:



number=20

a=2

b=1







s=0

for n in range(1,number+1):

s=s+a/b

#以下3句是程序的关键

t=a

a=a+b

b=t#以上3句可以改为a,b=a+b,a

print(s)





2. 迭代
迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程。迭代法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性操作的特点,让计算机重复执行一组指令(或一定步骤),在每次执行这组指令(或这些步骤)时都从变量的原值推出它的一个新值。
【例316】用迭代法求a的平方根。求平方根的公式为xn+1= (xn+a/xn)/2,求出的平方根的精度是前后项差的绝对值小于10-5。
分析: 用迭代法求a的平方根的算法如下。
(1) 设定一个x的初值x0(在如下程序中取x0=a/2)。
(2) 用求平方根的公式x1= (x0+a/x0) /2求出x的下一个值x1;求出的x1与真正的平方根相比,误差很大。
(3) 判断x1-x0的绝对值是否满足大于10-5,如果满足,则将x1作为x0,重新求出新的x1,如此继续下去,直到前后两次求出的x值(x1和x0)的差的绝对值满足小于10-5。
代码如下:



a=int(input("Input a positive number:"))#输入被开方数

x0 = a / 2;                               #任意取的初值

x1 = (x0 + a / x0) / 2                    #x0和x1分别代表前一项和后一项

while abs(x1 - x0)>0.00001:  #abs(x)函数用来求参数x的绝对值

x0 = x1

x1 = (x0 + a / x0) / 2

print("The square root is: " ,x1)





运行结果如下:



Input a positive number:2↙

The square root is: 1.4142137800471977






视频讲解



3.4程序的异常处理
程序在运行过程中总会遇到一些问题,例如编程人员要求输入数值数据,用户却输入字符串数据,这样必会导致严重错误。这些错误统称为异常,异常也称为例外,是在程序运行中发生的会打断程序正常执行的事件。Python提供了try…except…finally处理程序异常语句。
有时程序会出现一些错误或异常,导致程序中止,如做除法时除数为0,会引起一个ZeroDivisionError。例如: 



a=10

b=0

c=a/b

print("done")



程序的运行结果如下: 



Traceback(most recent call last):

File "C:/openfile.py", line 3, in <module>

c=a/b

ZeroDivisionError: integer division or modulo by zero



在运行时程序因为ZeroDivisionError而中断了,语句print("done")没有运行。为了保证程序运行的稳定性,这类运行异常错误应该被程序捕获并合理控制。Python提供了try…except…finally机制处理异常,语法格式如下: 



try:

可能触发异常的语句块

except [exceptionType]:

捕获可能触发的异常[可以指定处理的异常类型]

except [exceptionType][,date]:

捕获异常并获取附加数据

except:

没有指定异常类型,捕获任意异常

[else: 

没有触发异常时执行的语句块]

[finally: 

无论异常是否发生都要执行的语句块]



try…except的工作过程如下。
(1) 在执行一个try语句块时,当出现异常后,则向下匹配执行第一个与该异常匹配的except子句,如果没有找到与异常匹配的except子句(也可以不指定异常类型)将结束程序。 
更改上面的代码如下: 



a=10

b=0

try:

c=a/b

print(c)

except ZeroDivisionError,e:#处理ZeroDivisionError异常

print(e.message)

print("done")



程序的运行结果如下: 



integer division or modulo by zero

done



这样一来,程序就不会因为异常而中断,从而print ("done")语句正常执行。
在开发程序时把可能发生错误的语句放在try模块里,用except来处理异常。except可以处理一个专门的异常,也可以处理一组圆括号中的异常,如果except后没有指定异常,则默认处理所有的异常。每个try必须至少有一个except。
(2) 如果在try语句块执行时没有发生异常,Python将执行else中的语句,注意else语句是可选的,不是必需的。例如: 



a=10

b=0

try:

c = b/a

print c

except(IOError ,ZeroDivisionError),x:

print(x)

else:

print("no error")

print("done")



程序的运行结果如下: 



0

no error

done



其中IOError是输入/输出操作失败异常类,ZeroDivisionError是除0(或取模)异常类。
(3) 不管异常是否发生,在程序结束前finally中的语句都会被执行。例如:



a=10

b=0

try:

print(a/b)

except:

print("error")

finally:

print("always excute")



程序的运行结果如下: 



error

always excute







视频讲解



3.5游戏初步——猜单词游戏
【案例31】游戏初步——猜单词游戏。计算机随机产生一个单词,打乱字母的顺序,让玩家去猜。
分析: 在游戏中需要随机产生单词及随机数,所以引入random模块的随机数函数,其中random.choice()可以从序列中随机选取元素。例如: 



WORDS = ("python", "jumble", "easy", "difficult", "answer", "continue"

, "phone", "position", "pose", "game")

#从序列中随机挑出一个单词

word = random.choice(WORDS)





word就是从单词序列中随机挑出的一个单词。
在从游戏中随机挑出一个单词word后,如何把单词word的字母顺序打乱?方法是随机从单词字符串中选择一个位置position,把position位置上的字母加入乱序后的单词jumble,同时将原单词word中position位置上的字母删除(通过连接position位置前的字符串及其后字符串实现)。通过多次循环就可以产生新的乱序后的单词jumble。



while word: #word不是空串循环

#根据word的长度产生word的随机位置

position = random.randrange(len(word))

#将position位置上的字母组合到乱序后的单词

jumble += word[position]

#通过切片将position位置上的字母从原单词中删除

word = word[:position] + word[(position + 1):]

print("乱序后的单词:", jumble)





猜单词游戏程序的代码如下: 



#猜单词游戏

import random

#创建单词序列

WORDS = ("python", "jumble", "easy", "difficult", "answer", "continue",

"phone", "position", "position", "game")

#开始游戏

print(

"""

欢迎参加猜单词游戏

把字母组合成一个正确的单词.

"""

)

iscontinue="y"

while iscontinue=="y" or iscontinue=="Y":    

#从序列中随机挑出一个单词







word = random.choice(WORDS)

#一个用于判断玩家是否猜对的变量

correct = word

#创建乱序后的单词

jumble =""

while word: #word不是空串时循环

#根据word的长度产生word的随机位置


position = random.randrange(len(word))

#将position位置上的字母组合到乱序后的单词

jumble += word[position]

#通过切片将position位置上的字母从原单词中删除

word = word[:position] + word[(position + 1):]

print("乱序后的单词:", jumble)

guess = input("\n请你猜: ")

while guess != correct and guess != "":

print("对不起,不正确.")

guess = input("继续猜: ")

if guess == correct:

print("真棒,你猜对了!\n")

iscontinue=input("\n\n是否继续(Y/N): ")





运行结果如下: 



欢迎参加猜单词游戏

把字母组合成一个正确的单词.

乱序后的单词: yaes

请你猜: easy

真棒,你猜对了!

是否继续(Y/N): y

乱序后的单词: diufctlfi

请你猜: difficutl

对不起,不正确.

继续猜: difficult

真棒,你猜对了!

是否继续(Y/N): n

>>>





3.6习题
1. 输入一个整数n,判断其能否同时被5和7整除,如能则输出“xx能同时被5和7整除”,否则输出“xx不能同时被5和7整除”,要求xx为输入的具体整数。
2. 输入一个百分制的成绩,经判断后输出该成绩的对应等级。其中,90分以上为A,80~89分为B,70~79分为C,60~69分为D,60分以下为E。
3. 某百货公司为了促销采用购物打折的办法。消费1000元以上者,按九五折优惠; 消费2000元以上者,按九折优惠; 消费3000元以上者,按八五折优惠; 消费5000元以上者,按八折优惠。编写程序,输入购物款数,计算并输出优惠价。
4. 编写一个求整数n的阶乘(n!)的程序。
5. 编写程序,求1!+3!+5!+7!+9!。
6. 编写程序,计算下列公式中s的值(n是运行程序时输入的一个正整数)。

s =1 + (1 + 2) + (1 + 2 + 3) + … + (1 + 2 + 3 + … + n)

s =12+ 22 + 32 + … + (10×n+2)

s =1×2-2×3+3×4-4×5+ … +(-1) (n-1) ×n×(n+1) 


7. 百马百瓦问题: 有100匹马驮100块瓦,大马驮3块,小马驮两块,两个马驹驮一块,问大马、小马、马驹各有多少匹?
8. 有一个数列,其前3项分别为1、2、3,从第4项开始,每项均为其相邻的前3项之和的1/2,问该数列从第几项开始其数值超过1200?
9. 找出1~100内的全部同构数。同构数是这样一种数: 它出现在它的平方数的右端。例如,5的平方是25,5是25中右端的数,5就是同构数; 25也是一个同构数,它的平方是625。
10. 猴子吃桃问题: 猴子第一天摘下若干桃子,当即吃了一半,还不过瘾,又多吃了一个,第二天早上将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃前一天剩下的桃子的一半再加一个。到第10天早上想再吃时,发现只剩下一个桃子。求第一天共摘了多少个桃子。
11. 开发猜数字小游戏。计算机随机生成100以内的数字,让玩家去猜,如果猜的数字过大或过小都会给出提示,直到猜中该数,显示“恭喜!你猜对了”,同时要统计玩家猜的次数。
12. 数字重复统计问题。(1)随机生成1000个整数,数字的范围为[20,100]; (2)升序输出所有不同的数字及每个数字重复的次数。
13. 求每个学生的平均成绩,结果保留两位小数。




学生成绩s={"Teddy":[100,90,90],"Sandy":[100,90,80],"Elmo":[90,90,80]}





输出结果为{'Teddy': 93.3, 'Sandy': 90, 'Elmo': 86.7}。
14. 现有如下一个字典存放学生的学号和3门课程的成绩:



dictScore={"101":[67,88,45],"102":[97,68,85],"103":[98,97,95],"104":[67,48,45],"105":[82,58,75],"106":[96,49,65]}





编程返回每个学生的学号及其最高分。