全国计算机等级考试二级Python教材实例程序及编程习题
第一章 程序设计基本方法
实例1.1斐波那契数列计算
#CalFibonacci.py a,b=0,1 while a<1000: print(a,end=',') a,b=b,a+b
实例1.2 圆面积的计算
#CalCircleArea.py r=25 area=3.1415*r*r print(area) print("{:.2f}".format(area))
实例1.3绘制五角红星
1 #DrawStar.py 2 from turtle import* 3 color('red','red') 4 begin_fill() 5 for i in range(5): 6 fd(200) 7 rt(144) 8 end_fill() 9 done()
实例1.4 程序运行计时
1 #CalRunTime.py 2 import time 3 limit=10*1000*1000 4 start=time.perf_counter() 5 while True: 6 limit-=1 7 if limit<=0: 8 break 9 delta=time.perf_counter()-start 10 print("程序运行时间是:{}秒。".format(delta))
实例1.5绘制七彩圆圈
1 #DrawSevenColorfulCircles.py 2 import turtle 3 colors=['red','orange','yellow','green','blue','indigo','purple'] 4 for i in range(7): 5 c=colors[i] 6 turtle.color(c,c) 7 turtle.begin_fill() 8 turtle.rt(360/7) 9 turtle.circle(50) 10 turtle.end_fill() 11 turtle.done()
习题-基本编程题:
⒈悄悄话:
name=input('请输入对方名字:') s=input('请输入悄悄话的内容:') print("{},听我说句悄悄话:{}".format(name,s*3))
⒉九九乘法表
for i in range(1,10): for j in range(1,i+1): print("{}*{}={:2} ".format(j,i,i*j),end="") print("")
⒊同切圆
import turtle turtle.pensize(3) turtle.circle(20)#绘制半径为20像素的圆 turtle.circle(40)#绘制半径为40像素的圆 turtle.circle(80)#绘制半径为80像素的圆 turtle.circle(160)#绘制半径为160像素的
4.三个小爱好
hobbies="" for i in range(3): s=input('请输入你的小爱好(最多三个,按Q或q结束):') if s.upper()=='Q': break hobbies +=s+'' print('你的小爱好是:',hobbies)
⒌名字的幸运数
import random str1=input("请输入你的名字:") print("Hello!{}".format(str1)) guard=ord(str1[0])%100 print("你的幸运数字是",random.choice(range(guard)))
第二章 Python语言基本语法元素
实例解析——倒背如流
实例2.1
s=input("请输入一段文本:") i=len(s)-1 while i>=0: print(s[i],end="") i=i-1
实例2.2
s=input("请输入一段文本:") i=-1 while i>=-1*len(s): print(s[i],end="") i=i-1
实例2.3
s=input("请输入一段文本:") print(s[::-1])
习题-编程题:
⒈获得用户输入的一个整数lN,计算并输出N的32次方。
s=eval(input("请输入一个数字:")) print("{}的32次方是{}。".format(s,s**32))
⒉获得用户输入的一段文字,将这段文字进行垂直输出。
s = input("请输入一段文字:") for c in s: print(c)
⒊ 获得用户输入的一个合法算式,例如:1.2+3.4,输出运算结果。
result = eval(input("请输入一个合法算式(不含等号):")) print(result)
⒋ 获得用户输入的一个小数,提取并输出其整数部分。
a = eval(input("请输入一个小数:")) print(int(a))
⒌下面这段代码能够获得用户输入的一个整数N,计算并输出1到N相加的和。然而,这段代码存在多处语法错误,请指出错误所在并纠正。
1 n=input(“请输入整数N:”): 2 sum=0 3 for I in range(n) 4 sum+=i+1 5 print(“1到N求和结果:”.format(sum))
纠正的代码:
n = eval(input("请输入整数N:")) sum = 0 for i in range(n): sum += i+1 print("1到N求和结果:{}".format(sum))
第三章 基本数据类型
实例解析——恺撒密码
实例3.1
1 #CaesarEncode.py 2 ptxt=input("请输入明文文本:") 3 for p in ptxt: 4 if"a"<=p<="z": 5 print(chr(ord("a")+(ord(p)-ord("a")+3)%26),end='') 6 elif"A"<=p<="Z": 7 print(chr(ord("A")+(ord(p)-ord("A")+3)%26),end='') 8 else: 9 print(p,end='')
实例3.2
1 #CaesarDecode.py 2 ptxt=input("请输入加密后文本:") 3 for p in ptxt: 4 if"a"<=p<="z": 5 print(chr(ord("a")+(ord(p)-ord("a")-3)%26),end='') 6 elif"A"<=p<="Z": 7 print(chr(ord("A")+(ord(p)-ord("A")-3)%26),end='') 8 else: 9 print(p,end='')
实例3.3
1 s = """Gur Mra bs Clguba, ol Gvz Crgref 2 3 Ornhgvshy vf orggre guna htyl. 4 Rkcyvpvg vf orggre guna vzcyvpvg. 5 Fvzcyr vf orggre guna pbzcyrk. 6 Pbzcyrk vf orggre guna pbzcyvpngrq. 7 Syng vf orggre guna arfgrq. 8 Fcnefr vf orggre guna qrafr. 9 Ernqnovyvgl pbhagf. 10 Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf. 11 Nygubhtu cenpgvpnyvgl orngf chevgl. 12 Reebef fubhyq arire cnff fvyragyl. 13 Hayrff rkcyvpvgyl fvyraprq. 14 Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff. 15 Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg. 16 Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu. 17 Abj vf orggre guna arire. 18 Nygubhtu arire vf bsgra orggre guna *evtug* abj. 19 Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn. 20 Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn. 21 Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!""" 22 23 d = {} 24 for c in (65, 97): 25 for i in range(26): 26 d[chr(i+c)] = chr((i+13) % 26 + c) 27 print("".join([d.get(c, c) for c in s]))
实例3.4
1 #CaesarChineseEncode.py 2 ptxt=input("请输入明文文本:") 3 for p in ptxt: 4 if"a"<=p<="z": 5 print(chr(ord("a")+(ord(p)-ord("a")+3)%26),end='') 6 elif"A"<=p<="Z": 7 print(chr(ord("A")+(ord(p)-ord("A")+3)%26),end='') 8 elif 0x4E00<=ord(p)<= 0x9FA5: #中文字符加密处理 9 print(chr(ord(p)+3),end='') 10 else: 11 print(p,end='')
习题-编程题
⒊⒈获得用户输入的一个整数,输出该整数百位及以上的数字
1 s=input("请输入一个整数:") 2 s=int(s) 3 if 0<s<100: 4 print("请重新输入一个三位数的整数") 5 else: 6 s//=100 7 print(s)
⒊⒉获得用户输入的一个字符串,将字符串按照空格分割,然后逐行打印出来。
a=input("请输入一串字符:") a=a.split() for i in range(len(a)): print(a[i])
⒊⒊程序计入一个表示星期几的数字(1—7),输出对应的星期字符串名称。例如:输入3,返回“星期三”。
weeks = ['', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'] n = int(input('请输入一个表示星期几的数字(1——7): ')) print(weeks[n])
1 weeks = {'1': '星期一', '2': '星期二', 2 '3': '星期三', '4': '星期四', 3 '5': '星期五', '6': '星期六', 4 '7': '星期日' 5 } 6 7 n = input('请输入一个表示星期几的数字(1——7): ') 8 print(weeks.get(n))
⒊⒋设n是一任意自然数,如果n的各位数字反向排列所得自然数与n相等,则n被称为回文数。从键盘输入一个5位数字,请编写程序判断这个数字是不是回文数。
n=eval(input("请输入一个整数n:")) if str(n)==str(n)[::-1]: print("n为回文数") else: print("n不是回文数")
⒊⒌输入一个十进制整数,分别输出其二进制、八进制、十六进制字符串。
n = int(input('请输入一个十进制整数:')) print('对应的二进制:', bin(n)) print('对应的八进制:', oct(n)) print('对应的十六进制:', hex(n))
num = int(input('输入一个十进制整数:')) m = "{:b}".format(num)# 二进制 n = "{:o}".format(num)# 八进制 k = "{:x}".format(num)# 十六进制 print('对应的二进制:', m) print('对应的八进制:', n) print('对应的十六进制:', k)
第4章 程序的控制结构
示例:
4.2.1单分支结构:if
⒈判断非奇偶
#判断用户输入数字的奇偶性 s = eval(input("请输入一个整数:")) if s%2==0: print("这是个偶数") print("输入数字是:",s)
⒉判定数字特定性质
#判断用户输入数字的特定 s = eval(input("请输入一个整数:")) if s%3==0and s%5==0: print("这是个数既能被3整除,又能被5整除") print("输入数字是:",s)
4.2.2二分支结构:if-else
⒈判断数字的某个属性⑴
#判断用户输入数字的某个属性 s = eval(input("请输入一个整数:")) if s%3==0and s%5==0: print("这个数能够同时被3和5整除") else: print("这个数字不能够同时被3和5整除")
⒉判断数字的某个属性⑵
#判断用户输入数字的某个属性 s = eval(input("请输入一个整数:")) token="" if s%3==0and s%5==0 else"不" print("这个数{}能够同时被3和5整除".format(token))
4.2.3 多分支结构:if-elif-else
⒈将百分制成绩转换为五分制成绩(逻辑错误)
1 #将百分制成绩转换为五分制成绩 2 score = eval(input("请输入一个百分制成绩:")) 3 if score>=60.0: 4 grade="D" 5 elif score >= 70.0: 6 grade="C" 7 elif score>=80.0: 8 grade="B" 9 elif score>=90.0: 10 grade="A" 11 else: 12 grade="E" 13 print("对应的五分制成绩是:{}".format(grade))
输入80分会显示显然D,显然百分制80分不应该是等级D,上述代码运行正确但逻辑存在错误,弄错了多个逻辑条件的先后关系
⒉将百分制成绩转换为五分制成绩(正确)
1 #将百分制成绩转换为五分制成绩 2 score = eval(input("请输入一个百分制成绩:")) 3 if score>=90.0: 4 grade="A" 5 elif score >= 80.0: 6 grade="B" 7 elif score>=70.0: 8 grade="C" 9 elif score>=60.0: 10 grade="D" 11 else: 12 grade="E" 13 print("对应的五分制成绩是:{}".format(grade))
4.3.1遍历循环:for
⒈竖向输出字符串
for c in"Python": print(c)
⒉竖向输出数字
for i in range(5): print(i)
⒊遍历循环
for s in "PY": print("循环执行中:"+s) else: s="循环正常结束。" print(s)
4.3.2 无限循环:whil
⒈输出10以内的3的倍数
n=0 while n<10: print(n) n=n+3
⒉顺序输出字符串内容
1 s, idx="PY",0 2 while idx<len(s): 3 print("循环执行中:"+s[idx]) 4 idx+=1 5 else: 6 s="循环正常结束" 7 print(s)
4.3.3循环控制:break和continue
⒈特定条件退出程序
while True: s=input("请输入一个名字(按Q退出):") if s=="Q":#必须是大写 break print("输入的名字是:",s) print("程序退出")
⒉break退出最内层循环
1 while True: 2 s=input("请输入一个名字(按Q退出):") 3 if s=="Q": 4 break #退出while循环 5 for c in s: 6 if c=="E": 7 break #退出for循环但不退出while循环 8 print(c,end="") 9 print("程序退出")
⒊continue用来结束当前当次循环,即跳出循环体中下面尚未执行的语句,但不跳出当前循环。
for s in "PYTHON": if s=="Y": continue print(s,end="")
4.4程序的异常处理
当执行正常程序语句块1发生异常时,则执行excpet保留字后面的语句块2
⒈计算输入值的3次方
try: n=eval(input("请输入一个数字:")) print("输入数字的3次方的值为:",n**3) except: print("输入错误,请输入一个数字!")
⒉ 除零错误
try: for i in range(5): print(10/i,end=" ") except: print("某种原因,出错了!")
⒊增加指定错误类型
try: for i in range(5): print(10/i,end=" ") except ZeroDivisionError: print("除数为零,产生了除零错误!") except: print("某种原因,出错了!")
4.5实例解析——猜数字游戏
实例4.1
1 import random 2 target=random.randint(1,1000) 3 count=0 4 while True: 5 guess=eval(input('请输入一个猜测的整数(1至1000):')) 6 count=count+1 7 if guess>target: 8 print('猜大了') 9 elif guess<target: 10 print('猜小了') 11 else: 12 print('猜对了') 13 break 14 print("此轮的猜测次数是:",count)
实例4.2——增加异常处理,增加程序鲁棒性。
1 import random 2 target=random.randint(1,1000) 3 count=0 4 while True: 5 try: 6 guess=eval(input('请输入一个猜测的整数(1至1000):')) 7 except: 8 print('输入有误,请重试,不计入猜测次数哦!') 9 continue 10 count=count+1 11 if guess>target: 12 print('猜大了') 13 elif guess<target: 14 print('猜小了') 15 else: 16 print('猜对了') 17 break 18 print("此轮的猜测次数是:",count)
习题-编程题
⒈判断润年
输入一个年份,输出是否为闰年。#闰年条件:能被4整除但不能被100整除,或者 能被400整除的年份都是闰年。
①
1 years = int(input("请输入查询的年份: ")) 2 if years % 4 == 0 and years % 100 != 0: 3 print(years, "普通闰年") 4 elif years % 400 == 0: 5 print(years, "是世纪闰年") 6 else: 7 print("不是闰年")
②
years = int(input("请输入查询的年份: ")) if (years % 4 == 0 and years % 100 != 0) or (years % 400 == 0): print(years, "是闰年") else: print(years, "不是闰年")
⒉最大公约数计算。
最大公约数计算。获得两个整数,求出这两个整数的最大公约数和最小公倍数。最大公约数的计算一般使用辗转相除法,最小公倍数则使用两个数的乘积除以最大公约数。
1 s1=int(input("请输入第一个整数:")) 2 s2=int(input("请输入第二个整数:")) 3 A=s1 4 B=s2 5 C=0 6 S=A*B 7 if A<B: 8 A,B=B,A #如果A<B A、B交换位置 9 while A%B!=0: 10 C=A%B 11 A=B 12 B=C 13 var1=S//B 14 15 print("{}和{}的最大公约数是{},最小公倍数是{}".format(s1,s2,B,var1))
⒊ 统计不同字符个数。
统计不同字符个数。用户从键盘键入一行字符,编写一个程序,统计并输出其中英文字符、数字、空格和其他字符的个数。
1 s=input("请输入一行字符:\n") 2 alpha,num,space,other=0,0,0,0 3 for i in s: 4 if i.isalpha(): 5 alpha+=1 6 elif i.isdigit(): 7 num+=1 8 elif i.isspace(): 9 space+=1 10 else: 11 other+=1 12 print('英文字符数{},数字字符数{},\ 13 空格字符数{},其他字符数{}'\ 14 .format(alpha,num,space,other))
⒋猜数游戏续。
猜数游戏续。当用户输入的不是整数(如字母、浮点数等),时,程序会终止执行退出。改编题目1中的程序,当用户输入出错时给出“输入内容必须为整数!”的提示,并让用户重新输入。
1 import random 2 3 secret = random.randint(0,1000) #这里使用random()产生0~1000之间整数 4 #print(secret) 5 print('------猜数字游戏!-----') 6 guess = -1 7 N = 0 #记录次数 8 while guess != secret: 9 temp = input('请输入数字0~1000之间:\n') 10 if not temp.isdigit(): #判断输入的是否为非整数 11 print('输入内容必须为整数!!!!\n再来一次吧\n') 12 else: 13 N+=1 14 guess = int(temp) 15 if guess > secret: 16 print('遗憾,太大了!\n') 17 if guess < secret: 18 print('遗憾,太小了!\n') 19 if guess == secret: 20 print('你猜了{}次,猜中了!'.format(N))
⒌羊车门问题。
羊车门问题。有三扇关闭的门,一扇门后面停着汽车,其余门后是山羊,只有主持人知道每扇门后面是什么。参赛者可以选择一扇门,在开启它之前,主持人会开启另外一扇门,露出门后的山羊,然后允许参赛者更换自己的选择。请问:参赛者更换选择后能否增加猜中汽车的机会?——这是一个经典问题。请使用random库对这个随机事件进行预测,分别输出参赛者改变选择和坚持选择获胜的概率。
1 import random 2 x=random.randint(5000,10000) 3 change=0 4 nochange=0 5 for i in range(1,x+1): 6 a=random.randrange(1,4) 7 b=random.randrange(1,4) 8 if a==b: 9 nochange=nochange+1 10 else: 11 change=change+1 12 print("不更改选择得到汽车的概率为{:.2f}%。".format(nochange/x*100)) 13 print("更改选择得到汽车的概率为{:.2f}%。".format(change/x*100))
第5章 函数和代码复用
5.1函数的基本使用
5.1.1函数的定义
定义一个对整数n求阶乘的函数
#定义一个对整数n求阶乘的函数 def fact(n): s=1 for i in range(1,n+1): s*=i return s
使用:
>>> fact(3) 6 >>> fact(8) 40320 >>> fact(100) 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 >>>
5.1.2函数的使用
调用函数的基本方法正如下:
1 #定义一个对整数n求阶乘的函数 2 def fact(n): 3 s=1 4 for i in range(1,n+1): 5 s*=i 6 return s 7 #调用整数阶乘的函数 8 print(fact(100))
5.2函数的参数传递
5.2.1可选参数传递
def<函数名>(<非可选参数列表>,<可选参数>=<默认值>): <函数体> return<返回值列表>
5.2.2参数名称传递
<函数名>(<参数名>=<实际值>)
5.2.3函数的返回值
当函数存在多种结束条件时,将使用多个return语句,例如。
1 def manyret(x): 2 try: 3 if x>0: 4 return x+1 5 else: 6 return x-1 7 except: 8 return 0
5.3变量的作用域
局部变量仅在函数内部,且作用域也在函数内部。全局变量的作用域跨越多个函数。
5.3.1局部变量
局部变量指在函数内部定义的变量,仅在函数内部有效。
def multiply(x,y=10): z=x*y #z是函数内部的局部变量 return z
变量z是函数multiple()内部使用的变量,当函数调用后,变量z将不存在。
5.3.2 全局变量
全局变量在函数内部使用时,需要提前使用保留字global声明。
>>> n=2 >>> def multiply(x,y=10): global n return x*y*n #使用全局变量n >>> s=multiply(99,2) >>> print(s) 396 >>> print(n) 2
5.4代码复用
使用函数对程序合理划分为功能模块,并基于模块设计程序是一种常用方法,被称谓“模块化设计”。从系统观点来看,松耦合是总体设计原则。
5.5实例解析——软文的诗词风
实例5.1《将进酒·君不见》
1 txt=''' 2 人生得意顺尽欢,莫使金樽空对月。 3 天生我才必有用,千金散尽还复来。 4 ''' 5 linewidth=30#预定的输出宽度 6 7 def lineSplit(line): 8 plist=[',','!','?',',','。','!','.','?'] 9 for p in plist: 10 line=line.replace(p,'\n') 11 return line.split('\n') 12 13 def linePrint(line): 14 global linewidth 15 print(line.center(linewidth,chr(12288))) 16 17 newlines=lineSplit(txt) 18 for newline in newlines: 19 linePrint(newline)
实例5.2《三国演义》
txt=''' 三国演义 上卷 罗贯中 滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。 白发渔樵江渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。 ——调寄《临江仙》 第一回 宴桃园豪杰三结义 斩黄巾英雄首立功 话说天下大势,分久必合,合久必分。周末七国分争,并入于秦。及秦灭之后,楚、汉分争,又并入于汉。汉朝自高祖斩白蛇而起义,一统天下,后来光武中兴,传至献帝,遂分为三国。 ''' linewidth=30#预定的输出宽度 def lineSplit(line): plist=[',','!','?',',','。','!','.','?'] for p in plist: line=line.replace(p,'\n') return line.split('\n') def linePrint(line): global linewidth print(line.center(linewidth,chr(12288))) newlines=lineSplit(txt) for newline in newlines: linePrint(newline)
实例5.3《哈利波特与魔法石》
1 txt=txt=''' 2 第一部 第一章 幸存的男孩 3 4 住在四号普里怀特街的杜斯利先生及夫人非常骄傲地宣称自己是十分正常的人。但是他们最不希望 5 见到的就是任何奇怪或神秘故事中的人物因为他们对此总是嗤之以鼻。 6 7 杜斯利先生是一家叫作格朗宁斯的钻机工厂的老板。他非常肥壮结实几乎肥到没有颈根,但却有一 8 把大胡子。杜斯利夫人则非常苗条一头金发。她的颈根有常人的两倍那么长这使得她整天伸长脖子 9 透过花园围栏去偷窥邻居家的动静变得非常容易。杜斯利夫妇有个儿子叫做达德里。在他们眼中这 10 世界上再没有比达德里更棒的男孩了。 11 ''' 12 linewidth=30#预定的输出宽度 13 14 def lineSplit(line): 15 plist=[',','!','?',',','。','!','.','?'] 16 for p in plist: 17 line=line.replace(p,'\n') 18 return line.split('\n') 19 20 def linePrint(line): 21 global linewidth 22 print(line.center(linewidth,chr(12288))) 23 24 newlines=lineSplit(txt) 25 for newline in newlines: 26 linePrint(newline)
实例5.4《哈利波特与魔法石》
修改函数linePrint(),当一个短句字数超过限制时,分行居中显示。
1 txt=txt=''' 2 第一部 第一章 幸存的男孩 3 4 住在四号普里怀特街的杜斯利先生及夫人非常骄傲地宣称自己是十分正常的人。但是他们最不希望 5 见到的就是任何奇怪或神秘故事中的人物因为他们对此总是嗤之以鼻。 6 7 杜斯利先生是一家叫作格朗宁斯的钻机工厂的老板。他非常肥壮结实几乎肥到没有颈根,但却有一 8 把大胡子。杜斯利夫人则非常苗条一头金发。她的颈根有常人的两倍那么长这使得她整天伸长脖子 9 透过花园围栏去偷窥邻居家的动静变得非常容易。杜斯利夫妇有个儿子叫做达德里。在他们眼中这 10 世界上再没有比达德里更棒的男孩了。 11 ''' 12 linewidth=30#预定的输出宽度 13 14 def lineSplit(line): 15 plist=[',','!','?',',','。','!','.','?'] 16 for p in plist: 17 line=line.replace(p,'\n') 18 return line.split('\n') 19 20 def linePrint(line): 21 global linewidth 22 while len(line)>linewidth: 23 print(line[0:linewidth]) 24 line=line[linewidth:] 25 print(line.center(linewidth,chr(12288))) 26 27 newlines=lineSplit(txt) 28 for newline in newlines: 29 linePrint(newline)
编程题:
⒌⒈输入字符属性判断
实现isNum()函数,参数为一个字符串,如果这个字符串属于整数、浮点数或复数的表示,则返回Ture,否则返回False。
1 def isNum(): 2 try: 3 a = eval(input("请随机输入一个字符串:\n")) 4 if type(a) == int or type(a) == float or type(a) == complex: 5 print('True') 6 else: 7 print('False') 8 except: 9 print('False') 10 11 isNum()
⒌⒉质数判断
实现isPrime()函数,参数为整数,要有异常处理。如果整数是质数,返回Ture,否则返回False。
1 from math import sqrt 2 def isPrime(n): 3 if n == 1: 4 return False 5 for i in range(2,int(sqrt(n))+1): #在一般领域,对正整数n,如果用2到根号n之间的所有整数去除,均无法整除,则n为质数。 6 if n % i == 0: 7 return False 8 return True 9 10 while 1: #设置程序循环输入,如不需要循环可以删除 11 try: #异常处理 12 n = eval(input("请输入要判断的数字:")) 13 print(isPrime(n)) 14 except: #异常处理 15 print("格式输入错误,请重新输入一个数字,不要加入字母和其他特殊符号")
去掉循环:
1 from math import sqrt 2 def isPrime(n): 3 if n == 1: 4 return False 5 for i in range(2,int(sqrt(n))+1): #在一般领域,对正整数n,如果用2到根号n之间的所有整数去除,均无法整除,则n为质数。 6 if n % i == 0: 7 return False 8 return True 9 10 try: #异常处理 11 n = eval(input("请输入要判断的数字:")) 12 print(isPrime(n)) 13 except: #异常处理 14 print("格式输入错误,请重新输入一个数字,不要加入字母和其他特殊符号")
⒌⒊分类统计字符个数
编写一个函数计算传入字符串中数字、字母、空格以及其他字符的个数。
1 #编写一个函数计算传入字符串中数字、字母、空格以及其它字符的个数 2 def num(str1): 3 a = b = c = d = 0 4 for i in str1: 5 if i.isdigit(): 6 a += 1 7 elif i.isalpha(): 8 b += 1 9 elif i.isspace(): 10 c += 1 11 else: 12 d += 1 13 print("数字{}个,字母{}个,空格{}个,其他字符{}个".format(a,b,c,d)) 14 num(input("请输入一个字符串:"))
⒌⒋素数
编写一个函数,打印200以内的所有素数,以空格分割。
#编写一个函数,打印200以内的所有素数,以空格分隔 def issushu(n): if n < 2: return False else: for i in range(2,int(pow(n,0.5)+1)): if n % i == 0: return False else: return True def printsushu(): for i in range(0,201): if(issushu(i)): print(i,end = " ") printsushu()
⒌⒌第n个斐波那契数
编写一个函数,参数为一个整数n。利用递归获取斐波那契数列中的第n个数并返回。
1 def fib(n): 2 if n == 1: 3 return 1 4 elif n == 2: 5 return 1 6 elif n > 2: 7 return fib(n - 1) + fib(n - 2) 8 9 def main(): 10 n = eval(input("请输入一个整数:")) 11 print(fib(n)) 12 13 main()
第6章 组合数据类型
实例解析——文本词频统计
统计单词出现的次数:
counts[word]=counnts[word]+1
当遇到一个新词时:
counts[new_word]=1
因此,无论词是否在字典中,加入字典counts中的处理逻辑可以统一表示为:
if word in counts: counts[word]=counts[word]+1 else: counts[word]=1
或者,这个处理逻辑可以更简洁地表示为如下代码:
counts[word]=counts.get(word,0)+1
字典类型的counts.get(word,0)方法表示:如果word在counts中,则返回word对应的值;如果word不在counts中,则返回0。
该实例的第三步是对单词的统计值从高到低进行排序,输出前10个高频词语,并格式化打印输出。由于字典类型没有顺序,需要将其转换为有顺序的列表类型,再使用sort()方法和lambds函数配合实现根据单词次数对元素进行排序。最后输出排序结果前10位的单词。
items=list(counts.items())#将字典转换为记录列表 items.sort(key=lambda x:x[1],reverse=True)#以第2列排序
提示:lambda保留字
lambda用于定义一种匿名函数,住sort()用来根据第二列进行排序。
1 #CalHamlet.py 2 def getText(): 3 txt=open("hamlet.txt","r").read() 4 txt=txt.lower() 5 for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~': 6 txt=txt.replace(ch," ")#将文本中特殊字符替换为空格 7 return txt 8 hamletTxt=getText() 9 words=hamletTxt.split() 10 counts={} 11 for word in words: 12 counts[word]=counts.get(word,0)+1 13 items=list(counts.items()) 14 items.sort(key=lambda x:x[1],reverse=True) 15 for i in range(10): 16 word,count=items[i] 17 print("{0:<10}{1:>5}".format(word,count))
习题:
⒍⒈英文字符频率统计。
英文字符频率统计。编写一个程序,对给定字符串中出现的a~z字母频率进行分析,忽略大小写,采用降序方式输出。
①刷屏效果:
1 txt = input("请输入一段英文文本:") 2 txt = txt.lower() 3 d = {} 4 for i in txt: 5 if i in "abcdefghijklmnopqrstuvwxyz": 6 d[i] = d.get(i,0) + 1 # 字典中的值 7 ls = list(d.items()) 8 ls.sort(key = lambda x:x[1],reverse = True) # 排序用的 9 for i in range(len(d)): 10 word,count = ls[i] 11 print("{:<10}{:<5}".format(word,count))
②简明效果
1 txt=input("请输入一段英文文本:") 2 txt=txt.lower() 3 counts={} 4 for i in txt: 5 if i in "abcdefghijklmnopqrstuvwxyz": 6 counts[i]=counts.get(i,0)+1 7 items=list(counts.items()) 8 items.sort(key=lambda x:x[1],reverse=True) 9 for i in range(len(items)): 10 word,count=items[i] 11 print("{0:<10}{1:>5}".format(word,count))
⒍⒉中文字符频率统计。
中文字符频率统计。编写一个程序,对给定字符串中出现的全部字符(含中文字符)频率进行分析,采用降序方式输出。
1 txt = input("请输入一段汉字文本:") 2 d = {} 3 for i in txt: 4 d[i] = d.get(i,0) + 1 # 字典中的值 5 ls = list(d.items()) 6 ls.sort(key = lambda x:x[1],reverse = True) # 排序用的 7 for i in range(len(d)): 8 word,count = ls[i] 9 print("{:<10}{:<5}".format(word,count))
⒍⒊随机密码生成。
随机密码生成。编写程序在26个字母大小写和9个数字组成的列表中随机生成10个8位密码。
方法①
1 import random 2 s = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", 3 "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", 4 "0","1","2","3","4","5","6","7","8","9"] #根据要求定义列表元素范围,无要求时也可定义字符串更方便 5 6 for i in range(10): #循环10遍,生成10组密码 7 for i in range(8): 8 print (random.choice(s),end="") #random.choice(seq)实现从序列或集合seq中随机选取一个元素 9 print("\n") #每输出一组后,换行输出下一组
方法②
1 import random 2 s = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", 3 "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", 4 "0","1","2","3","4","5","6","7","8","9"] #根据要求定义列表元素范围,无要求时也可定义字符串更方便 5 6 for i in range(10): #循环10遍,生成10组密码 7 k = random.sample(s,8) #random.sample(seq, k)实现从序列或集合seq中随机选取k个独立的的元素,以列表形式输出 8 for i in k: #遍历随机数组中的每一项并输出 9 print(i,end="") 10 print("\n") #每输出一组后,换行输出下一组
⒍⒋重复元素判定。
重复元素判定。编写一个函数,接收列表作为参数,如果一个元素在列表中出现了不止一次,则返回True,但不要改变原来列表的值。同时编写调用这个函数和输出测试结果的程序。(这个得用Ctrl+C结束运行)
1 def Lbpd(a): #定义函数Lbpd(a) 2 a =a.split(" ") #对参数a按照空格进行分词 3 if len(a)==len(set(a)): #利用集合的不重复性,比较列表a和集合a的长度 4 return "False,这是非重复序列" #如相同则返回非重复序列 5 else: 6 return "True,这是重复序列" #如不同则返回重复序列 7 t = f = 0 #重复序列和非重复序列次数初始赋值 8 9 while True: #让程序循环运行 10 a =input("请输入一组序列,以空格隔开:") 11 print(Lbpd(a)) #调用函数,打印函数参数为a时的返回值 12 if Lbpd(a)=="True,这是重复序列": #统计重复序列次数 13 t +=1 14 if Lbpd(a)=="False,这是非重复序列": #统计非重复序列次数 15 f +=1 16 print("重复序列{}次,非重复序列{}次".format(t,f)) #打印输出统计结果语句
⒍⒌重复元素判定续。
重复元素判定续。利用集合的无重复性改编上一个程序,获得一个更快更简洁的版本。
①这个需要输入列表
ls = eval(input("请输入一个列表:")) if ls != list(set(ls)): print(True) else: print(False)
②
1 def chachong(c): 2 b=c.split(" ") 3 b = [int(b[i]) for i in range(len(b))] 4 a = set(b) 5 if len(a) != len(b): 6 return True 7 else: 8 return False 9 10 11 print('请输入数字: (用空格隔开)') 12 a = input('')
第7章 文件和数据格式化
7.1文件的使用
7.1.1文件的类型
①一个文本文件a.txt,采用文本方式打开。需要将文本文件与Python程序文件放在同一个目录中。
f=open("a.txt","rt")#t表示文本文件方式打开 print(f.readline()) f.close()
②文本文件a.txt采用二进制方式打开。
f=open("a.txt","rb")#b表示文本文件方式打开 print(f.readline()) f.close()
7.1.2文件的打开和关闭
‘r’ 只读模式,如果文件不存在,返回异常FileNotFoundError,默认值
‘w’ 覆盖写模式,文件不存在则创建,存在则完全覆盖原文件
‘x’ 创建写模式,文件不存在则创建,存在则返回异常FileExisisError
‘a’ 追加写模式,文件不存在则创建,存在则在原文件最后追加内容
‘b’ 二进制文件模式
‘t’ 文本文件模式,默认值
‘+’ 与r/w/x/a一同使用,在原功能基础上增加同时读写功能
7.1.3文件读写
f.read(size=-1) 从文件中读入整个文件内容。参数可选,如果给出,读入前size长度的字符串或字节流
f.readline(size=-1) 从文件中读入一行内容。参数可先,如果给出,读入该行前size长度的字符串或字节流
f.readlines(hint=-1) 从文件中读入所有行,以每行为元素形成一个列表。参数可先,如果给出,读入hint行
f.seek(offset) 改变当前文件操作指针的位置,offset的值:0为文件开头;2为文件结尾
f.write(s) 向文件写入一个字符串或字节流
f.writelines(lines) 将一个元素为字符串的列表整体写入文件
7.2数据组织的维度
7.2.1一维数据
一维数据采用线性方式组织,对应于数学中数组的概念。
7.2.2二维数据
二维数据,采用二维表格方式组织,对应于数学中的矩阵。
7.2.3 高维数据
高维数据由键值对类型的数据构成,采用对象方式组织,可以多层嵌套。
7.3 一维数据的处理
7.3.1一维数据的表示
一维数据是最简单的线性结构的数据组织类型,在Python语言中主要采用列表形式表示。
7.3.2一维数据的存储
常用的4种存储方法:
⑴空格分隔;⑵逗号分隔;⑶换行分隔;⑷其他特殊符号分隔。
CSV格式是一种通用的、相对简单的文件格式,大部分编辑器都支持直接读入或保存文件为CSV格式。
一维数据保存成CSV格式后,各元素采用逗号分隔,形成一行。
列表对象输出为CSV格式文件方法如下,采用字符串的join()方法最为方便。
ls=['北京','上海','天津','重庆'] f=open("city.csv","w") f.write(",".join(ls)+"\n") f.close()
程序执行后生成的city.csv文件内容如下:
北京,上海,天津,重庆
7.3.3 一维数据的处理
从CSV格式文件读入一维数据,并将其表示为列表对象。
从CSV文件中获得内容时,最后一个元素后面包含了一个换行符(”\n”),需要采用字符串的strip()方法去掉数据尾部的换行符,进一步使用split()方法以逗号进行分割。
ls=['北京','上海','天津','重庆'] f=open("city.csv","w") f.write(",".join(ls)+"\n") f.close()
程序执行后列表对象ls的内容如下。
['北京', '上海', '天津', '重庆']
7.4二维数据的处理
7.4.1 二维数据的表示
二维数据由多个一维数据构成,可以采用二维列表来表示。
1 ls=[ 2 ['指标','2014年','2015年','2016年'], 3 ['居民消费价格指数','102','101.4','102'], 4 ['食品','103.1','102.3','104.6'], 5 ['烟酒及用品','994','102.1','101.5'], 6 ['衣着','102.4','102.7','101.4'], 7 ['家庭设备用品','101.2','101','100.5'], 8 ['医疗保健和个人用品','101.3','102','101.1'], 9 ['交通和通信','99.9','98.3','98.7'], 10 ['娱乐教育文化','101.9','101.4','101.6'], 11 ['居住','102','100.7','101.6'], 12 ]
二维数据一般采用相同的数据类型存储数据。
本例中数值所在行或列不都是数字,存在字符文本,因此,将数值统一表示为字符串形式。
7.4.2 二维数据的存储
二维数据由一维数据组成,用CSV格式文件存储。CSV文件的每一行是一维数据,整个CSV文件是一个二维数据。cpi.csv:
1 指标,2014年,2015年,2016年 2 居民消费价格指数,102,101.4,102 3 食品,103.1,102.3,104.6 4 烟酒及用品,994,102.1,101.5 5 衣着,102.4,102.7,101.4 6 家庭设备用品,101.2,101,100.5 7 医疗保健和个人用品,101.3,102,101.1 8 交通和通信,99.9,98.3,98.7 9 娱乐教育文化,101.9,101.4,101.6 10 居住,102,100.7,101.6
二维列表对象输出为CSV格式文件:
1 ls=[ 2 ['指标','2014年','2015年','2016年'], 3 ['居民消费价格指数','102','101.4','102'], 4 ['食品','103.1','102.3','104.6'], 5 ['烟酒及用品','994','102.1','101.5'], 6 ['衣着','102.4','102.7','101.4'], 7 ['家庭设备用品','101.2','101','100.5'], 8 ['医疗保健和个人用品','101.3','102','101.1'], 9 ['交通和通信','99.9','98.3','98.7'], 10 ['娱乐教育文化','101.9','101.4','101.6'], 11 ['居住','102','100.7','101.6'], 12 ] 13 f=open("cpi.csv","w") 14 for row in ls: 15 f.write(",".join(row)+"\n") 16 f.close()
7.4.3 二维数据的处理
对二维数据进行处理首先需要从CSV格式文件读入二维数据,并将其表示为二维列表对象。
1 f=open("cpi.csv","r") 2 ls=[] 3 for line in f: 4 ls.append(line.strip('\n').split(",")) 5 f.close() 6 print(ls)
程序执行后二维列表对象ls的内容如下。
>>> [['指标', '2014年', '2015年', '2016年'], ['居民消费价格指数', '102', '101.4', '102'], ['食品', '103.1', '102.3', '104.6'], ['烟酒及用品', '994', '102.1', '101.5'], ['衣着', '102.4', '102.7', '101.4'], ['家庭设备用品', '101.2', '101', '100.5'], ['医疗保健和个人用品', '101.3', '102', '101.1'], ['交通和通信', '99.9', '98.3', '98.7'], ['娱乐教育文化', '101.9', '101.4', '101.6'], ['居住', '102', '100.7', '101.6']]
对二维数据进行格式化输出,打印成表格形式:
1 f=open("cpi.csv","r") 2 ls=[] 3 for line in f: 4 ls.append(line.strip('\n').split(",")) 5 f.close() 6 for row in ls: 7 line="" 8 for item in row: 9 line+="{:14}\t".format(item) 10 print(line)
经过再次循环遍历,二维数据的所有元素都将被处理,输出效果如下:
指标 2014年 2015年 2016年 居民消费价格指数 102 101.4 102 食品 103.1 102.3 104.6 烟酒及用品 994 102.1 101.5 衣着 102.4 102.7 101.4 家庭设备用品 101.2 101 100.5 医疗保健和个人用品 101.3 102 101.1 交通和通信 99.9 98.3 98.7 娱乐教育文化 101.9 101.4 101.6 居住 102 100.7 101.6 >>>
7.5实例解析——国家财政数据趋势演算
1 # FinancePredict.py 2 def parseCSV(filename): 3 dataNames, data = [], [] 4 f = open(filename, 'r', encoding='utf-8') 5 for line in f: 6 splitedLine = line.strip().split(',') 7 if '指标' in splitedLine[0]: 8 years = [int(x[:-1]) for x in splitedLine[1:]] 9 else: 10 dataNames.append('{:10}'.format(splitedLine[0])) 11 data.append([float(x) for x in splitedLine[1:]]) 12 f.close() 13 return years, dataNames, data 14 15 def means(data): 16 return sum(data) / len(data) 17 18 def linearRegression(xlist, ylist): 19 xmeans, ymeans = means(xlist), means(ylist) 20 bNumerator = - len(xlist) * xmeans * ymeans 21 bDenominator = - len(xlist) * xmeans ** 2 22 for x, y in zip(xlist, ylist): 23 bNumerator += x * y 24 bDenominator += x ** 2 25 b = bNumerator / bDenominator 26 a = ymeans - b * xmeans 27 return a, b 28 29 def calNewData(newyears, a, b): 30 return [(a + b * x) for x in newyears] 31 32 def showResults(years, dataNames, newDatas): 33 print('{:^60}'.format('国家财政收支线性估计')) 34 header = '指标 ' 35 for year in years: 36 header += '{:10}'.format(year) 37 print(header) 38 for name, lineData in zip(dataNames, newDatas): 39 line = name 40 for data in lineData: 41 line += '{:>10.1f}'.format(data) 42 print(line) 43 44 def main(): 45 newyears = [x+2010 for x in range(7)] 46 newDatas = [] 47 years, dataNames, datas = parseCSV('finance.csv') 48 for data in datas: 49 a, b = linearRegression(years, data) 50 newDatas.append(calNewData(newyears, a, b)) 51 showResults(newyears, dataNames, newDatas) 52 53 main()
运行结果如下:
国家财政收支线性估计 指标 2010 2011 2012 2013 2014 2015 2016 全部收入 105359.6 114550.1 123740.6 132931.0 142121.5 151312.0 160502.4 中央收入 48169.1 52283.8 56398.5 60513.2 64627.9 68742.7 72857.4 地方收入 57190.6 62266.3 67342.1 72417.8 77493.6 82569.3 87645.1 全部支出 122936.9 133645.7 144354.5 155063.3 165772.1 176480.9 187189.8 中央支出 19037.5 20390.9 21744.3 23097.7 24451.1 25804.5 27157.9 地方支出 103899.4 113254.8 122610.2 131965.6 141321.0 150676.4 160031.9 >>>
实例中设计了6个函数,分别是parseCSV()/、means()、linearRegression()、calNewData()、showResults()、main()。
parseCSV()用来解析CSV文件,从中读取数据,并把数据表示为列表类型。其中需要关注的代码如下:
years=[int(x[:-1])for x in splitedLine[1:]]
这是for循环的一种紧凑形式,它指的是从splitedLine[1:]中逐一取出元素x,并对该元素执行表达式int(x[:-1])。这种紧凑形式对简化代码整体逻辑十分有益。
means()用来计算所有数据的均值。
linearRegression()用来根据xlist和ylist列表计算线性回归值。其中需要关注的是zip()函数的使用,代码如下。使用zip()可以同时对xlist和ylist进行同步遍历,每次取出各自一个元素x和y,并进行关联操作。
for x, y in zip(xlist, ylist): bNumerator += x * y bDenominator += x ** 2
calNewData()用来计算新的数值。
showResults()集中展示运行结果,重点在于格式化输出。
main()代表该程序的主逻辑部分,包括预分配列表变量、调用各步骤或流程函数等。
编程题:
⒈输入一个文件和一个字符,统计该字符在文件出现的次数。
(提前准备好一个文本文件,放在此代码文件相同目录(文件夹)内)
1 def times(filename,char): 2 count=0 3 f=open(filename,'r',encoding='utf-8') 4 txt=f.read() 5 txt=txt.lower() 6 for word in txt: 7 if char==word: 8 count+=1 9 f.close() 10 return count 11 a=input("请输入文件名称(全名,包括文件名后缀):") 12 b=input("请输入一个字符,以统计此字符在文件中的重复次数:") 13 print("字符{}在文件{}中重复的次数为{}次。".format(b,a,times(a,b)))
⒉假设有一个英文文本文件,编写一个程序读取其内容并将里面的大写字母变成小写字母,小写字母变成大写字母。
1 a=input("请输入文件名:") 2 f = open(a,'r') 3 s = f.readlines() 4 f.close() 5 r = [i.swapcase() for i in s] 6 f = open(r'改变大小写.txt','w') 7 f.writelines(r) 8 f.close() 9 print("转换大小写完毕,并保存为“改变大小写.txt”文件")
⒊编写一个程序,生成一个10×10的随机矩阵并保存为文件(空格分隔行向量、换行分隔列向量),再写程序将刚才保存的矩阵文件另存为CSV格式,用Excel或文本编辑器打开看看结果对不对。
1 import random 2 def s_txt(low,high,txtname): 3 f = open("{}.txt".format(txtname),"w") 4 for line in range(10): 5 word = "" 6 for row in range(10): 7 word = word + str(random.randrange(low,high)) + " " 8 f.write(word + "\n") 9 f.close() 10 11 def s_csv(txtname,csvname): 12 f1 = open("{}.txt".format(txtname),"r") 13 f2 = open("{}.csv".format(csvname),"w") 14 for line in f1: 15 after = line.replace(" ",",") 16 f2.write(after) 17 f1.close() 18 f2.close() 19 20 def main(): 21 low,high = eval(input("请输入随机数下限low、上限high,并用逗号隔开:")) 22 txtname = input("请输入txt文件名:") 23 s_txt(low,high,txtname) 24 csvname = input("请输入csv文件名:") 25 s_csv(txtname,csvname) 26 27 main()
⒋编写一个程序,读取一个Python源代码文件,将文件中所有除保留字外的小写字母换成大写字母,生成后的文件要能够被Python解释器正确执行。
1 # -*- coding: utf-8 -*- 2 3 import jieba 4 import re 5 import os; 6 n=input("输入一个文件名:") 7 fo= open(n,"r",encoding='utf-8').read() 8 9 table=["def","for","in","return","print","range"] 10 words = jieba.lcut(fo) 11 n2='-2' 12 str_list=list(n) 13 str_list.insert(-3,n2) 14 n_n2=''.join(str_list) 15 16 fo2=open(n_n2,"w") 17 pas='' 18 for i in range(0,len(words)): 19 20 if words[i] in table: 21 pass; 22 23 else: 24 words[i]=words[i].upper() 25 pas="".join(words) 26 fo2.write(pas) 27 fo2.close()
⒌编写一个程序,要求能够将元素为任意Python支持的类型(包括含有半角逗号的字符串)的列表转储为CSV,并能够重新正确解析为列表。
1 def save_csv(ls, fname): 2 # 向列表中逐个添加元素 3 value = input('请向列表总添加一个元素:') 4 while value != '': 5 ls.append(value) 6 value = input('请向列表总添加一个元素:') 7 print('您输入的列表为:{}'.format(ls)) 8 9 # 若元素中有半角逗号,将其替换成点 10 for i in range(len(ls)): 11 if ',' in ls[i]: 12 ls[i] = ls[i].replace(',', '.') 13 14 file_csv = open('{}.csv'.format(fname), 'w', encoding='utf-8') 15 file_csv.write(','.join(ls) + '\n') 16 file_csv.close() 17 print('恭喜!已成功保存<{}.csv>文件!'.format(fname)) 18 19 20 def read_csv(lt, fname): 21 f = open('{}.csv'.format(fname), 'r', encoding='utf-8') 22 lt = f.read().strip('\n').split(',') 23 24 # 将替换后的点换成半角逗号 25 for i in range(len(lt)): 26 if '.' in lt[i]: 27 lt[i] = lt[i].replace('.', ',') 28 f.close() 29 print('<{}.csv>文件读取中...'.format(fname)) 30 print(lt) 31 32 33 def main(): 34 ls = [] 35 fname = input('请将列表文件命名:') 36 save_csv(ls, fname) 37 lt = [] 38 read_csv(lt,fname) 39 40 main()
第8章 Python计算生态
8.1计算思维
是笨办法求和
sum=0 for i in range(1,101): sum+=i print(sum)
8.2程序设计方法论
“体育竞技分析”的实例
8.2.1自顶向下设计
步骤1:打印程序的介绍性信息;
步骤2:获得程序运行需要的参数:probA,probB,n;
步骤3:利用球员A和B的能力值probA和probB,模拟n次比赛;
步骤4:输出球员A和B获胜比赛的场次及概率。
①顶层设计一般不写出具体代码,仅给出函数定义
def min(): printIntro()
②获得用户输入,假设程序调用了getInputs()函数,获取变量probA、probB、和n的值,这个函数必须为主程序返回这些值。
def min():
printIntro() probA,probB,n=getInputs()
③使用probA、probB的模拟n场比赛:
def min(): printIntro() probA,probB,n=getInputs() winsA,winsB=simNGames(n,probA,probB)
④输出结果:
def min(): printIntro() probA,probB,n=getInputs() winsA,winsB=simNGames(n,probA,probB) printSummary(winsA,winsB)
printIntro()函数:
def printIntro(): print(“这个程序模拟两个选手A和B的某种竞技比赛”) print(“程序运行需要A和B的能力值(以0到1之间的小数表示)”)
getInputs()函数根据提示得到3个需要返回主程序的值
def getInputs(): a=eval(input(“(请输入选手A的能力值(0~1):”)) b=eval(input(“请输入选手B的能力值(0~1):”)) n=eval(input(“模拟比赛的场次:”)) return a,b,n
simNGames()函数是整个程序的核心,其基本思路是模拟n场比赛
1 def simNGames(n,probA,probB): 2 winsA,winsB=0,0 3 for i in range(n): 4 scoreA,scoreB=simOneGame(probA,probB) 5 if scoreA>scoreB: 6 winsA+=1 7 else: 8 winsB+=1 9 return winsA,winsB
simOneGam()函数,了模拟一场比赛。
1 def simOneGame(probA, probB): 2 scoreA, scoreB = 0, 0 3 serving = "A" 4 while not gameOver(scoreA, scoreB): 5 if serving == "A": 6 if random() < probA: 7 scoreA += 1 8 else: 9 serving="B" 10 else: 11 if random() < probB: 12 scoreB += 1 13 else: 14 serving="A" 15 return scoreA, scoreB
gameOver()函数,当任意一个球员分数达到15分时比赛结束。
def gameOver(a,b): return a==15 or b==15
最后是printSummary()函数
def printSummary(winsA, winsB): n = winsA + winsB print("竞技分析开始,共模拟{}场比赛".format(n)) print("选手A获胜{}场比赛,占比{:0.1%}".format(winsA, winsA/n)) print("选手B获胜{}场比赛,占比{:0.1%}".format(winsB, winsB/n))
将上述所有代码放在一起,形成了实例全部代码
1 #MatchAnalysis.py 2 from random import random 3 def printIntro(): 4 print("这个程序模拟两个选手A和B的某种竞技比赛") 5 print("程序运行需要A和B的能力值(以0到1之间的小数表示)") 6 def getInputs(): 7 a=eval(input("(请输入选手A的能力值(0~1):")) 8 b=eval(input("请输入选手B的能力值(0~1):")) 9 n=eval(input("模拟比赛的场次:")) 10 return a,b,n 11 def simNGames(n,probA,probB): 12 winsA,winsB=0,0 13 for i in range(n): 14 scoreA,scoreB=simOneGame(probA,probB) 15 if scoreA>scoreB: 16 winsA+=1 17 else: 18 winsB+=1 19 return winsA,winsB 20 def gameOver(a,b): 21 return a==15 or b==15 22 def simOneGame(probA, probB): 23 scoreA, scoreB = 0, 0 24 serving = "A" 25 while not gameOver(scoreA, scoreB): 26 if serving == "A": 27 if random() < probA: 28 scoreA += 1 29 else: 30 serving="B" 31 else: 32 if random() < probB: 33 scoreB += 1 34 else: 35 serving="A" 36 return scoreA, scoreB 37 def printSummary(winsA, winsB): 38 n = winsA + winsB 39 print("竞技分析开始,共模拟{}场比赛".format(n)) 40 print("选手A获胜{}场比赛,占比{:0.1%}".format(winsA, winsA/n)) 41 print("选手B获胜{}场比赛,占比{:0.1%}".format(winsB, winsB/n)) 42 def main(): 43 printIntro() 44 probA,probB,n=getInputs() 45 winsA,winsB=simNGames(n,probA,probB) 46 printSummary(winsA,winsB) 47 main()
整体设计逐渐向下进行。每一层以大体算法描述开始,然后逐步细化成代码,细节被函数封装,整个过程可以概括为4个步骤:
步骤1:将算法表达为一系列小问题;
步骤2:为每个小问题设计接口;
步骤3:通过将算法表达为接口关联的多个小问题来细化算法;
步骤4:为每个小问题重复上述过程。
8.2.2自底向上执行
import<源文件名称>
可以对gameOver()函数进行单元测试