版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
函数第五章课程目标课程目标1了解程序员为什么将程序分成多组合作的函数324熟练掌握函数的定义及调用。掌握变量的作用范围及使用global定义全局变量。了解lambda函数的功能及使用。5利用函数来编程,减少代码重复并增加程序的模块性PART1函数的功能1函数的功能在前面的示例中只用到main函数,我们还使用了预先编写的函数和方法,包括:内置的Python函数(如print、abs)来自Python标准库的函数和方法(如math.sqrt)来自graphics模块的方法(如myPoint.getX())函数是构建复杂程序的重要工具。1函数的功能终值问题的图形解决方案:程序利用graphics库来绘制显示投资增长的柱形图。win=GraphWin("InvestmentGrowthChart",320,240)win.setCoords(-1.75,-200,11.5,10400)改进后的代码如下:fromgraphicsimport*defmain():print("10年的本金增长情况")#输入本金和利率
principal=float(input("输入初始本金:"))apr=float(input("输入利率:"))#创建图形窗口
win=GraphWin("投资增长图表",320,240)win.setBackground("white")win.setCoords(-1.75,-200,11.5,10400)Text(Point(-1,0),'0.0K').draw(win)Text(Point(-1,2500),'2.5K').draw(win)Text(Point(-1,5000),'5.0K').draw(win)Text(Point(-1,7500),'7.5k').draw(win)Text(Point(-1,10000),'10.0K').draw(win)1函数的功能
#为初始本金画柱
bar=Rectangle(Point(0,0),Point(1,principal))bar.setFill("green")bar.setWidth(2)bar.draw(win)#为每一年画柱
foryearinrange(1,11):principal=principal*(1+apr)bar=Rectangle(Point(year,0),Point(year+1,principal))bar.setFill("green")bar.setWidth(2)bar.draw(win)print("点击任意处退出")win.getMouse()win.close()main()在程序风格方面有点啰嗦在两个不同的地方绘制柱形(初始柱形在循环之前绘制,而随后的柱形在循环内绘制)终值问题的图形解决方案:程序利用graphics库来绘制显示投资增长的柱形图。1函数的功能一个程序有两个地方有类似的代码,就会产生一些问题:必须写两次代码代码必须在两个不同的地方维护未能保持代码的相关部分同步是程序维护中的常见问题。函数可用于减少代码重复,并使程序更易于理解和维护。PART2函数的非正式讨论2函数的非正式讨论函数定义
将函数想象成一个“子程序”,函数的基本思想是写一个语句序列,并给这个序列取一个名字,然后可以通过引用函数名称,在程序中的任何位置执行这些指令。函数调用创建函数的程序部分称为“函数定义”当函数随后在程序中使用时,我们称该定义被“调用”单个函数定义可以在程序的许多不同位置被调用2函数的非正式讨论编写一个程序,打印”HappyBirthday”的歌词,标准歌词如下:Happybirthdaytoyou!Happybirthdaytoyou!Happybirthday,dear<insert-name>.Happybirthdaytoyou!2函数的非正式讨论如果按照前面的思想使用一个main函数,则我们可以使用四个print函数来实现:defmain():print("Happybirthdaytoyou!")print("Happybirthdaytoyou!")print("Happybirthday,dearFred.")print("Happybirthdaytoyou!")可行,但啰嗦2函数的非正式讨论我们引入一个函数来表示第一行、第二行和第四行歌词:>>>defhappy():print("Happybirthdaytoyou!")#此时,main函数就可以变成:defmain(): happy() happy() print("Happybirthday,dearFred.") happy()使用函数可以极大的减小代码量简洁2函数的非正式讨论FredLucyElmer多人生日,也可以利用函数的方法来简化程序。2函数的非正式讨论
上面已经实现了为一个人过生日,我们将这个函数取名为singLucy(),则此时主函数main()可以写为如下:defmain(): singFred() singLucy() singElmer()三个函数除了第三句的名字不同外,其余的都是一样的。2函数的非正式讨论可以将三个函数用一个函数表示:defsing(person):happy()happy()print("HappyBirthday,dear",person+".")happy()#此时的主函数main就变成了这样:defmain(): sing("Fred") print() sing("Lucy") print() sing("Elmer") print()PART3带有函数的终值程序3带有函数的终值程序终值问题主要是柱形在两段代码的绘制,先来看看这两段代码:bar=Rectangle(Point(0,0),Point(1,principal))bar.setFill("green")bar.setWidth(2)bar.draw(win)bar=Rectangle(Point(year,0),Point(year+1,principal))bar.setFill("green")bar.setWidth(2)bar.draw(win)循环之前的代码循环中的代码3带有函数的终值程序终值问题主要是柱形在两段代码的绘制,先来看看这两段代码:bar=Rectangle(Point(0,0),Point(1,principal))bar.setFill("green")bar.setWidth(2)bar.draw(win)bar=Rectangle(Point(year,0),Point(year+1,principal))bar.setFill("green")bar.setWidth(2)bar.draw(win)循环之前的代码循环中的代码VS3带有函数的终值程序将两段代码合并,定义一个函数:defdrawBar(window,year,height): bar=Rectangle(Point(year,0),Point(year+1,height)) bar.setFill("green") bar.setWidth(2) bar.draw(window)第一个循环可以写成drawBar(win,0,2000)3带有函数的终值程序利用drawBar函数的完整代码如下:fromgraphicsimport*defdrawBar(window,year,height):bar=Rectangle(Point(year,0),Point(year+1,height))bar.setFill("green")bar.setWidth(2)bar.draw(window)defmain():print("10年的本金增长情况")#输入本金和利率
principal=float(input("输入初始本金:"))apr=float(input("输入利率:"))#创建GraphWin并设置标题和窗口大小
win=GraphWin("投资增长图表",320,240)3带有函数的终值程序利用drawBar函数的完整代码如下:win.setBackground("white")win.setCoords(-1.75,-200,11.5,10400)Text(Point(-1,0),'0.0K').draw(win)Text(Point(-1,2500),'2.5K').draw(win)Text(Point(-1,5000),'5.0K').draw(win)Text(Point(-1,7500),'7.5k').draw(win)Text(Point(-1,10000),'10.0K').draw(win)drawBar(win,0,principal)foryearinrange(1,11):principal=principal*(1+apr)drawBar(win,year,principal)input("按<enter>退出.")win.close()main()可以看到drawBar如何消除了重复的代码如果我们希望改变图形中柱形的外观,只需要在一个地方改变drawBar的定义PART4函数和参数4函数和参数defdrawBar(window,year,height):为什么window也是这个函数的参数呢?柱形图的可变部分使用window参数的原因与函数定义中变量的“范围”有关范围是指在程序中可以引用给定变量的位置我们将在同一个窗口中绘制所有的柱形,它似乎没有改变。4函数和参数在一个函数内部使用的变量是该函数的“局部”变量,即使它们与另一个函数中的变量具有相同的名称函数要看到另一个函数中的变量,唯一方法是将该变量作为参数传入每个函数本身都是一个小子程序。4函数和参数由于GraphWin(分配给变量win)是在main内部创建的,因此不能在drawBar中直接访问。当drawBar被调用时,drawBar中的window参数被赋值为win的值。4函数和参数我们需要更详细地了解函数调用的过程。函数定义如下:def<name>(<formal-parameters>):<body>必须是标识符是变量名(也是标识符)的序列(可能为空)形参与函数中使用的所有变量一样,只能在函数体中访问在程序其他地方,具有相同名称的变量与函数体内的形参和变量不同4函数和参数函数的调用是使用其名称后跟“实参”或“参数”的列表。<name>(<actual-parameters>)Python遇到一个函数调用时,启动一个四步过程:
调用程序在调用点暂停执行。函数的形参获得由调用中的实参提供的值。执行函数体。控制返回到函数被调用之后的点。4函数和参数图5.1函数执行happy的过程
当Python遇到第一句sing(“Fred”),main函数暂停,此时跳转到sing函数,并且sing函数具有单个实参。在这里,Python开始执行sing的函数体,当遇到happy函数时,sing函数体暂停,此时跳转到happy函数,执行print函数,输出结果,执行完毕后就会返回到它的上一级。4函数和参数图5.2函数执行sing的过程执行以这种方式继续,Python又绕路去了两次happy,完成了sing的执行。当Python到达sing的末尾时,控制就返回到main,并在函数调用之后紧接着继续。图6-2显示了此时我们的位置。注意,sing中的person变量已经消失了。函数完成时,会回收局部函数变量占用的内存。局部变量不保留从一个函数执行到下一个函数执行的任何值。4函数和参数图5.3第二次调用sing的过程
下一个要执行的语句是main中的空白print语句。这将在输出中生成空行。然后Python遇到另一个对sing的调用。如前所述,控制转移到函数定义。这次形参是“Lucy”。图6-3展示了第二次开始执行时的情况。4函数和参数
后面的过程就和执行Fred的过程一样了。main中这三句话导致sing执行了两次、happy执行了六次。总共产生了9行输出。第一个实参第一个形参当函数定义具有多个参数时,实参按位置与形参匹配。第二个实参第二个形参4函数和参数绘制初始柱形的调用drawBar(win,0,principal)Python将控制转移到drawBar时,这些参数与函数标题中的形参匹配drawBar(win,0,principal)实际效果就像函数体以三个赋值语句开头window=winyear=0height=principal作为示例,再看看终值程序中
drawBar
函数的使用。调用函数时,必须始终小心,将实参的顺序写正确,以符合函数定义PART5返回值的函数第二课时5返回值的函数在数学上,函数调用实际上是一个产生结果的表达式。从math库调用sqrt函数:discRt=math.sqrt(b*b-4*a*c)值是math.sqrt函数的实参由于函数调用发生在赋值语句的右侧,这意味着它是一个表达式math.sqrt函数生成一个值,然后将该值赋给变量discRt技术上,我们说sqrt返回其参数的平方根5返回值的函数编写返回值的函数非常容易。这是一个函数的Python实现,返回其参数的平方:defsquare(x): returnx**2当Python遇到return时,它立即退出当前函数,并将控制返回到函数被调用之后的点return语句中提供的值作为表达式结果发送回调用者函数的返回值用作表达式的结果函数的主体由一个return语句组成5返回值的函数用square函数来写另一个函数,找到两点之间的距,,给定两个点(x1,y1)和(x2,y2),它们之间的距离是
:defdistance(p1,p2):dist=math.sqrt(square(p2.getX()-p1.getX())+square(p2.getY()-p1.getY())returndist
这是一个Python函数,计算两个Point对象之间的距离:5返回值的函数计算三角形的周长结合第4章学到的graphics允许用户通过点击图形窗口中的三个点来绘制一个三角形利用距离公式求该三角形的周长importmathfromgraphicsimport*defsquare(x):returnx**2defdistance(p1,p2):dist=math.sqrt(square(p2.getX()-p1.getX())+square(p2.getY()-p1.getY()))returndist5返回值的函数defmain():win=GraphWin("绘制三角形",700,700)win.setCoords(0.0,0.0,10.0,10.0)message=Text(Point(5,0.5),"任意点击三个点")message.draw(win)#获取并绘制三角形的三个顶点
p1=win.getMouse()p1.draw(win)p2=win.getMouse()p2.draw(win)p3=win.getMouse()p3.draw(win)
#利用Polygon对象来绘制三角形
triangle=Polygon(p1,p2,p3)triangle.setFill("peachpuff")triangle.setOutline("cyan")triangle.draw(win)5返回值的函数
#计算三角形的周长
perim=distance(p1,p2)+distance(p2,p3)+distance(p3,p1)message.setText("该三角形的周长为:{0:0.2f}".format(perim))#点击任意位置退出
win.getMouse()win.close()main()三次调用了distance函数,这样可以减少很多的冗余,使得代码看起来简单易懂返回值的函数非常有用、灵活,因为它们可以组合在这样的表达式中5返回值的函数程序中函数定义的顺序并不重要,如果让main函数在顶部定义,同样能工作只要确保在程序实际尝试运行函数之前定义函数因为直到模块的最后一行才会发生main()的调用,所以所有的函数在程序实际开始运行之前已被定义5返回值的函数回到HappyBirthday程序。在最初的版本中,我们使用了几个包含print语句的函数。我们可以不让辅助函数执行打印,而是简单地让它们返回值,然后由main打印。defhappy():return"HappyBirthdaytoyou!\n"defverseFor(person):lyrics=happy()*2+"Happybirthday,dear"+person+".\n"+happy()returnlyricsdefmain():forpersonin["Fred","Lucy","Elmer"]:print(verseFor(person))main()在verseFor函数中就像数学表达式一样,将整个句子建立在单个字符串表达式中版本的程序也比原来的更灵活5返回值的函数打开一个文件进行写入,并在print语句中添加一个“file=”参数,不需要修改其他函数。修改版本:defmain():outf=open("Happy_Birthday.txt","w")forpersonin["Fred","Lucy","Elmer"]:print(verseFor(person),file=outf)outf.close()同时,return可以返回多个值,举个简单例子:defmain():a=x*yb=x/yreturna,bPART6修改参数的函数6修改参数的函数返回值是从函数发送信息到调用函数的程序部分的主要方式。在某些情况下,函数还可以通过更改函数参数来与调用程序通信。理解何时以及如何实现这一点,需要掌握Python如何赋值的一些微妙细节,以及这对函数调用中使用的实参和形参之间关系的影响。6修改参数的函数假设一个人的基础成绩为base_grade,通过一个月的努力学习成绩会在原来的基础上提高value,此时,需要编写一个程序计算每个月的成绩。假设我们的最初程序为如下:defgrade(base_grade,value):newgrade=base_grade*(1+value)base_grade=newgrade6修改参数的函数
此时,我们写一个测试程序来验证。假设我们的基础成绩设置为1,提高的value为0.1,则经过一个月的努力学习后,成绩应该变为1.1。deftest():test_grade=1test_value=0.1grade(test_grade,test_value)print(test_grade)test()结果却为1test函数的前两行创建了名为test_grade和test_value的两个局部变量,它们分别具有初始值1和0.1。6修改参数的函数图5.4控制转移到grade
控制转移到grade函数。形参base_grade和value被实参test_grade和value赋值。记住,value为局部变量,所以两函数中的value是两个单独的变量。grade开始执行的情况如图6-4所示。注意,参数的赋值导致grade中的变量base_grade和value引用了实参的“值”。6修改参数的函数图5.5base_grade赋值执行grade的第一行,则会生成newgrade,随后将newgrade的值赋值到base_grade,如下图6-5所示。但是新生成的base_grade值对test函数中的test_grade没有影响,所以最后得到的结果并不会改变。6修改参数的函数函数的形参只接收实参的“值”该函数不能访问保存实参的变量为形参分配新值对包含实参的变量没有影响用编程语言的术语,Python“按值”传递所有参数6修改参数的函数
在Python中不允许引用传递参数,我们可以使用return函数让值返回newgrade并用于更新test_grade,修改的代码如下:defgrade(base_grade,value):newgrade=base_grade*(1+value)returnnewgradedeftest():test_grade=1test_value=0.1test_grade=grade(test_grade,test_value)print(test_grade)test()结果为1.1,符合要求6修改参数的函数FredLucyElmer……如要为多为同学同时记录他们成绩的变化,我们就需要编写一个能处理多为同学的程序。由于每位同学的基础不同,所以他们的base_grade不同,我们可以将他们的所有base_grade以列表的形式存储。6修改参数的函数通过索引的方式,将他们的计算结果对应的存储在列表的对应位置,如下:base_grade[i]=base_grade[i]*(1+value)i表示第i个人这段代码就表示将第i个人的基础成绩乘以(1+value),在存储到base_grade列表的第i个位置。6修改参数的函数要遍历所有的成员,则可以采用循环的方式,参考代码如下:defgrade(base_grade,value):foriinrange(len(base_grade)):base_grade[i]=base_grade[i]*(1+value)deftest():test_grade=[1,2,4,8]test_value=0.1grade(test_grade,test_value)print(test_grade)test()运行程序得到如下结果:[1.1,2.2,4.4,8.8]PART7变量的作用域7变量的作用域一个复杂的程序包含多个自定义函数,每个函数定义的变量只能在一定范围内起作用,这种情况称为变量的作用域。不同作用域中即使两个变量的名字相同,但两者毫无任何关系,互不影响。变量作用域分为全局变量和局部变量两种。无论是局部变量还是全局变量,其作用域都是从定义的位置开始的,在此之前定义的内容无法访问。局部变量是指在函数内部使用的变量,仅在该函数内部有效,当函数退出时变量也不再存在。7变量的作用域局部变量应用举例。
deftestA():
a=100print(a)testA()#100print(a)#报错NameError:name'a'isnotdefined
上述局部变量a作用域仅在函数内部。
全局变量是指在所有函数定义之外定义的变量,它通常没有缩进,在程序执行过程中全程有效,可以与局部变量重名。7变量的作用域全局变量应用举例。
a=100deftestA():
print(a)print(a)#100deftestB():
a=200print(a)testA()#100testB()#200print(a)#100
通过运行结果可以看到,a变量在不同作用域内作用不同。7变量的作用域局部变量转变成全局变量的应用举例。a=100deftestA():
print(a)print(a)#100deftestB():
globalaa=200print(a)testA()#100testB()#200print(a)#200通过运行结果可以看到,调用函数testB()后,函数体内的局部变量a通过global函数变成了全局变量。PART8lambda函数8lambda函数·lambda函数只能定义能够在一行内表示的函数。·lambda函数表达式只可以包含一个表达式,不允许包含其他复杂的语句,但是在表达式中可以调用其他函数,表达式的运算结果相当于函数的返回值。·如果通过lambda函数仅定义一些简单的运算,建议使用系统提供的内置函数进行处理,因为内置函数的执行效果更高。说明lambda函数又称匿名函数,它是一种特殊的函数,通过保留字lambda定义该函数,匿名函数并非没有函数名,而是将函数名作为函数结果返回。lambda函数常用在临时需要一个类似函数功能但不想定义函数的场合。lambda函数定义方法,如下:
<函数名>=lambda<参数>:<表达式>PART9函数和程序结构9函数和程序结构函数化程序能减少代码量,使程序看起来更简单有时候就算增加函数可能使得程序看起来更长,但是依然会乐此不疲,因为函数可以使得程序更模块化将复杂问题分块化,即将复杂问题拆解为一个个简单的问题,依次解决这些简单的问题,最后复杂问题也能迎刃而解。程序函数化也利用了这个思想。当遇到很复杂的问题时,使用函数可以让我们更好理解。处理复杂问题时的思想9函数和程序结构如我们将终值问题使用函数表示,可以得到最终代码如下:fromgraphicsimport*defcreateLabeledWindow():window=GraphWin("InvestmentGrowthChart",320,240)window.setBackground("white")window.setCoords(-1.75,-200,11.5,10400)Text(Point(-1,0),'0.0K').draw(window)Text(Point(-1,2500),'2.5K').draw(window)Text(Point(-1,5000),'5.0K').draw(window)Text(Point(-1,7500),'7.5k').draw(window)Text(Point(-1,10000),'10.0K').draw(window)returnwindowdefdrawBar(window,year,height):bar=Rectangle(Point(year,0),Point(year+1,height))bar.setFill("green")bar.setWidth(2)bar.draw(window)9函数和程序结构如我们将终值问题使用函数表示,可以得到最终代码如下:defmain():print("Thisprogramplotsthegrowthofa10yearinvestment.")principal=float(input("Entertheinitialprincipal:"))apr=float(input("Entertheannualized
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 花主题活动策划方案(3篇)
- 自制活动小屋方案策划(3篇)
- 砖垫层施工方案(3篇)
- 大白-涂料施工方案(3篇)
- 地面吸声施工方案(3篇)
- 大型干渠施工方案(3篇)
- 放学音乐活动方案策划(3篇)
- 企业国际化运营与管理规范(标准版)
- 短视频直播策划方案
- 2025年高职云计算技术与应用(云计算应用)试题及答案
- 设计公司报账管理办法
- DB51∕T 3045-2023 四川省社会保险基本公共服务规范
- 毕业设计(论文)-自动展开晒衣架设计
- 智能化系统在铁路装备检修中的应用-洞察阐释
- TCPQSXF006-2023消防水带产品维护更换及售后服务
- 2025四川眉山市国有资本投资运营集团有限公司招聘50人笔试参考题库附带答案详解
- 边坡喷锚施工方案
- YS/T 3045-2022埋管滴淋堆浸提金技术规范
- 项目进度跟进及完成情况汇报总结报告
- 峨眉山城市介绍旅游宣传课件
- 浙江省温州市乐清市2023-2024学年五年级上学期期末语文试题
评论
0/150
提交评论