中国大学MOOCPython语言程序设计(北京理工大学)第5-6周学习笔记和课后练习
第5周 函数与代码复用
5.1 函数的定义与使用
使用保留字def定义函数,lambda定义匿名函数
可选参数(赋初值)、可变参数(*b)、名称传递
保留字return可以返回任意多个结果
保留字global声明使用全局变量,一些隐式规则
5.2 实例7: 七段数码管绘制
理解方法思维
模块化思维:确定模块接口,封装功能
规则化思维:抽象过程为规则,计算机自动执行
化繁为简:将大功能变为小功能组合,分而治之
代码:
# coding:utf-8
import turtle,time
def drawGap():
turtle.penup()
turtle.fd(5)
def drawLine(draw):
drawGap()
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
drawGap()
turtle.right(90)
def drawDigit(digit):
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup()
turtle.fd(20)
def drawDate(date):
turtle.pencolor("red")
for i in date:
if i =="-":
turtle.write("年",font=("Arial",18,"normal"))
turtle.pencolor("green")
turtle.fd(40)
elif i =="=":
turtle.write("月",font=("Arial",18,"normal"))
turtle.pencolor("red")
turtle.fd(40)
elif i =="+":
turtle.write("日",font=("Arial",18,"normal"))
turtle.pencolor("blue")
else:
drawDigit(eval(i))
def main():
turtle.setup(800,350,200,200)
turtle.penup()
turtle.fd(-300)#由绘图中心原点向左300像素
turtle.pensize(5)
drawDate(time.strftime("%Y-%m=%d+",time.gmtime()))
turtle.hideturtle()
turtle.done()
main()
5.3 代码复用与函数递归
模块化设计:松耦合、紧耦合
函数递归的2个特征:基例和链条
函数递归的实现:函数 + 分支结构
汉诺塔问题
count=0
def hanoi(n,src,dst,mid):
global count
if n==1:
print("{}:{}>{}".format(1,src,dst))
count+=1
else:
hanoi(n-1,src,mid,dst)
print("{}:{}>{}".format(n,src,dst))
count+=1
hanoi(n-1,mid,dst,src)
hanoi(3,"A","B","C")
print(count)
5.4 模块4: PyInstaller库的使用
PyInstaller库常用参数
参数 描述
-h 查看帮助
–clean 清理打包过程中的临时文件
-D, --onedir 默认值,生成dist文件夹
-F, --onefile 在dist文件夹中只生成独立的打包文件
-i <图标文件名.ico> 指定打包程序使用的图标(icon)文件
5.5 实例8: 科赫雪花小包裹
科赫曲线,也叫雪花曲线
分形几何是一种迭代的几何图形,广泛存在于自然界中
分形几何千千万
康托尔集、谢尔宾斯基三角形、门格海绵…
龙形曲线、空间填充曲线、科赫曲线…
函数递归的深入应用
代码:
#科赫雪花曲线1一阶
#KochDraw1.py
import turtle
def koch(size,n):
if n==0:
turtle.fd(size)
else:
for angle in [0,60,-120,60]:
turtle.left(angle)
koch(size/3,n-1)
def main():
turtle.setup(800,400)
turtle.penup()
turtle.goto(-350,-50)
turtle.pendown()
turtle.pensize(2)
koch(600,3)
turtle.hideturtle()
main()
#科赫雪花曲线2 三阶
import turtle
def koch(size,n):
if n==0:
turtle.fd(size)
else:
for angle in [0,60,-120,60]:
turtle.left(angle)
koch(size/3,n-1)
def main():
turtle.setup(800,600)
turtle.penup()
turtle.goto(-200,100)
turtle.pendown()
turtle.pensize(2)
koch(400,level)
turtle.right(120)
koch(400,level)
turtle.right(120)
koch(400, level)
turtle.hideturtle()
level=3#也可以直接在题目中设置局部变量
main()
第6周 组合数据类型
6.1 集合类型及操作
集合使用{}和set()函数创建
集合间操作:交(&)、并(|)、差(-)、补(^)、比较(>=<)
集合类型方法:.add()、.discard()、.pop()等
集合类型主要应用于:包含关系比较、数据去重
6.2 序列类型及操作
序列是基类类型,扩展类型包括:字符串、元组和列表
列表取反
元组用()和tuple()创建,列表用[]和set()创建
元组操作与序列操作基本相同
列表操作在序列操作基础上,增加了更多的灵活性
6.3 实例9: 基本统计值计算
获取多个数据:从控制台获取多个不确定数据的方法
分隔多个函数:模块化设计方法
充分利用函数:充分利用Python提供的内置函数
#基本统计值计算
def getNum():#获取用户不定长输入
nums=[]
iNumStr=input("请输入数字(回车退出):")
while iNumStr!="":
nums.append(eval(iNumStr))
iNumStr = input("请输入数字(回车退出):")
return nums
def mean(numbers):#计算平均值
s=0.0
for num in numbers:
s+=num
return s/len(numbers)
#计算标准差
def dev(numbers,mean):
sdev=0.0
for num in numbers:
sdev+=(num-mean)**2
return pow(sdev/(len(numbers)-1),0.5)
#计算中位数
def median(numbers):
numbers.sort()
#使用sorted函数必须有返回值
#或者numbers=numbers.sorted()
size=len(numbers)
if size%2==0:
med=(numbers[size//2-1]+numbers[size//2])/2
else:
med=numbers[size//2]
return med
n=getNum()
m=mean(n)
print("平均值是{},标准差是{:.2},中位数是{}".format(m,dev(n,m),median(n)))
6.4 字典类型及操作
映射关系采用键值对表达
字典类型使用{}和dict()创建,键值对之间用:分隔
d[key] 方式既可以索引,也可以赋值
字典类型有一批操作方法和函数,最重要的是.get()
6.5 模块5: jieba库的使用
jieba分词依靠中文词库
利用一个中文词库,确定中文字符之间的关联概率
中文字符间概率大的组成词组,形成分词结果
除了分词,用户还可以添加自定义的词组
jieba分词的三种模式:
精确模式、全模式、搜索引擎模式
精确模式:把文本精确的切分开,不存在冗余单词
全模式:把文本中所有可能的词语都扫描出来,有冗余
搜索引擎模式:在精确模式基础上,对长词再次切分
6.6 实例10: 文本词频统计
文本去噪及归一化
中文文本分词
使用字典表达词频
扩展程序解决问题
文本词频统计:英文版哈姆雷特
#calHamletV1.py
def getText():
txt=open("hamlet.txt","r").read()
txt=txt.lower()
for ch in "!#$%&()*+,-./:;<=>?@[\\]^_‘{|}~":
txt=txt.replace(ch," ")
return txt
hamletTxt=getText()
words=hamletTxt.split()
counts={}
for word in words:
counts[word]=counts.get(word,0)+1
items=list(counts.items())
items.sort(key=lambda x:x[1],reverse=True)
for i in range(10):
word,count=items[i]
print("{0:<10}{1:>5}".format(word,count))
对中文文本词频统计:
# coding:utf-8
import jieba
txt=open("threekingdoms.txt", "r",encoding="UTF-8").read()
excludes = {"将军","却说","荆州","二人","不可","不能","如此",
"商议","如何","天下","左右","主公","军马","军士","引兵","次日","东吴"}
#没统计完还有很多词汇需要排除
words=jieba.lcut(txt)
counts={}
for word in words:
if len(word)==1:
continue
elif word == "诸葛亮" or word == "孔明曰":
rword = "孔明"
elif word == "关公" or word == "云长":
rword = "关羽"
elif word == "玄德" or word == "玄德曰":
rword = "刘备"
elif word == "孟德" or word == "丞相":
rword = "曹操"
else:
counts[word]=counts.get(word,0)+1
for word in excludes:
del counts[word]
items=list(counts.items())
items.sort(key=lambda x:x[1],reverse=True)
for i in range(15):
word,count=items[i]
print("{0:<10}{1:>5}".format(word,count))
课后练习:字典翻转输出
注意点:
审题,题目说读入一个字典类型的字符串。
字典翻转输出其实是将键值对进行调换,使用 input 函数获取输入,使用eval函数去除引号并赋值给变量 S,这时的变量是获取的字典。随后遍历字典S,并将S的键和值重新赋值给字典dict,其实就是读取现有的字典然后重新创建字典并输出。
如果还是不太理解我们可以将S[i] 这段代码拆分出来,使用 print 语句进行输出,他其实获取的是字典 S 的值,我们将值当做键 dict[S[i]] 然后将键i当做值重新添加到字典 dict 中。
s=input()
try:
S=eval(s)
dict={}
for i in S:
dict[S[i]]=i
print(dict)
except:
print("输入错误")
课后练习:《沉默的羔羊》之最多单词
附件是《沉默的羔羊》中文版内容,请读入内容,分词后输出长度大于2且最多的单词。
如果存在多个单词出现频率一致,请输出按照Unicode排序后最大的单词。
# #《沉默的羔羊》之最多单词
import jieba
f=open("沉默的羔羊.txt","r",encoding="UTF-8").read()
words=jieba.lcut(f)
counts={}
for word in words:
counts[word]=counts.get(word,0)+1
maxc = 0
maxw = ""
for k in words:
if counts[k] > maxc and len(k) > 2:
maxc = counts[k]
maxw = k
if counts[k] == maxc and len(k) > 2 and k > maxw:
maxw = k
print(maxw)
单元测试程序题
1.数字不同数之和
描述
获得用户输入的一个整数N,输出N中所出现不同数字的和。
例如:用户输入 123123123,其中所出现的不同数字为:1、2、3,这几个数字和为6。
N=input()
s=set(N)
sum=0
for i in s:
sum+=eval(i)
print(sum)
2.人名最多数统计
描述
编程模板中给出了一个字符串,其中包含了含有重复的人名,请直接输出出现最多的人名。
#2.人名最多数统计
# #编程模板中给出了一个字符串,其中包含了含有重复的人名,请直接输出出现最多的人名。
s = '''双儿 洪七公 赵敏 赵敏 逍遥子 鳌拜 殷天正 金轮法王 乔峰 杨过 洪七公 郭靖
杨逍 鳌拜 殷天正 段誉 杨逍 慕容复 阿紫 慕容复 郭芙 乔峰 令狐冲 郭芙
金轮法王 小龙女 杨过 慕容复 梅超风 李莫愁 洪七公 张无忌 梅超风 杨逍
鳌拜 岳不群 黄药师 黄蓉 段誉 金轮法王 忽必烈 忽必烈 张三丰 乔峰 乔峰
阿紫 乔峰 金轮法王 袁冠南 张无忌 郭襄 黄蓉 李莫愁 赵敏 赵敏 郭芙 张三丰
乔峰 赵敏 梅超风 双儿 鳌拜 陈家洛 袁冠南 郭芙 郭芙 杨逍 赵敏 金轮法王
忽必烈 慕容复 张三丰 赵敏 杨逍 令狐冲 黄药师 袁冠南 杨逍 完颜洪烈 殷天正
李莫愁 阿紫 逍遥子 乔峰 逍遥子 完颜洪烈 郭芙 杨逍 张无忌 杨过 慕容复
逍遥子 虚竹 双儿 乔峰 郭芙 黄蓉 李莫愁 陈家洛 杨过 忽必烈 鳌拜 王语嫣
洪七公 韦小宝 阿朱 梅超风 段誉 岳灵珊 完颜洪烈 乔峰 段誉 杨过 杨过 慕容复
黄蓉 杨过 阿紫 杨逍 张三丰 张三丰 赵敏 张三丰 杨逍 黄蓉 金轮法王 郭襄
张三丰 令狐冲 赵敏 郭芙 韦小宝 黄药师 阿紫 韦小宝 金轮法王 杨逍 令狐冲 阿紫
洪七公 袁冠南 双儿 郭靖 鳌拜 谢逊 阿紫 郭襄 梅超风 张无忌 段誉 忽必烈
完颜洪烈 双儿 逍遥子 谢逊 完颜洪烈 殷天正 金轮法王 张三丰 双儿 郭襄 阿朱
郭襄 双儿 李莫愁 郭襄 忽必烈 金轮法王 张无忌 鳌拜 忽必烈 郭襄 令狐冲
谢逊 梅超风 殷天正 段誉 袁冠南 张三丰 王语嫣 阿紫 谢逊 杨过 郭靖 黄蓉
双儿 灭绝师太 段誉 张无忌 陈家洛 黄蓉 鳌拜 黄药师 逍遥子 忽必烈 赵敏
逍遥子 完颜洪烈 金轮法王 双儿 鳌拜 洪七公 郭芙 郭襄 赵敏'''
#传统解法,先使用字典建立"姓名与出现次数"的关系,然后找出现次数最多数对应的姓名。
#初始化空字典
dict={}
#将字符串分割
words=s.split()
#对字典中元素进行遍历
for i in words:
dict[i]=dict.get(i,0)+1
max_name,max_cnt="",0
#遍历字典
for k in dict:
if dict[k] > max_cnt:
max_name,max_cnt=k,dict[k]
print(max_name)
#还有一个方法简洁点
#将结果用列表表示,每一项都是一个元组,存放key和value
#result=list(dict.items())
#也可以使用sort函数排序
#result.sort(key=lambda x:x[1],reverse=True)
#print(result[0][0])