版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Python语言程序设计基础12-8月-26第六章函数第6章函数本章学习目标掌握函数的定义与调用方法理解位置参数、默认值参数、关键字参数、可变参数和传递参数时的序列解包理解变量作用域掌握高阶函数、Lambda表达式等Python函数式编程目录1函数的定义与调用函数概述2
函数参数3变量作用域4递归函数56Python函数式编程7函数的综合应用案例6.1函数概述6.1.1函数的基本概念函数是模块化程序设计的基本构成单位,它允许我们编写一段代码并在需要时多次调用它。函数可以接受任意数量的输入参数,并返回一个或多个值。
函数是可重用的代码段,在实际开发中,把可能需要反复执行的代码封装为函数,在需要执行该代码段时可以调用封装好的函数。6.1.2函数的功能1.模块化:函数可以将复杂的程序分解成更小、更易于管理的部分,使得程序更加模块化,提高了代码的可读性和可维护性。2.代码重用:通过将常用的代码块封装成函数,可以在程序中的多个地方重复调用该函数,减少代码冗余,提高代码的复用率。3.参数传递:函数可以接受参数并返回结果,使得代码更加灵活,可以根据不同的输入得到不同的输出。4.错误处理:在函数内部可以添加异常处理逻辑,当函数执行过程中出现错误时,可以按照预设的逻辑处理错误,保证程序的稳定性。5.功能封装和抽象:函数可以将一组相关的操作代码块封装在一起,对外只提供调用的接口,隐藏了内部的实现细节,使得代码更加抽象、简洁和通用。6.1.2函数的功能6.流程控制:通过函数的返回值,可以实现流程的控制和判断,使得代码更加清晰和易于理解。7.复用和组合:函数可以相互调用,形成复杂的逻辑关系,构建出强大的程序。8.减少全局变量的使用:在函数内部定义的变量只在函数内部有效,称为局部变量。这种局部变量的作用域可以避免全局变量的滥用,使代码更加可控和易于维护。9.可扩展性:当需要增加新的功能时,可以定义新的函数来实现新的功能,而不需要修改已有的代码。6.1.3函数的分类在Python语言中,函数主要分为如下4类:1.内置函数:Python语言内置了许多常用的函数,例如len()、str()、max()等。内置函数不需要额外导入任何模块即可直接使用,运行速度非常快。2.标准库函数:在标准的Python安装包中包含若干标准库,例如math、random、datatime等。通过import语句可导入标准库,然后使用其中定义的函数。3.扩展库函数:Python社区提供了大量第三方扩展库,例如numpy、pandas、sklearn等。开发人员根据需要安装合适的扩展库后,可通过import语句导入扩展库,然后使用其中定义的函数。4.用户自定义函数:用户自己根据需求定义的函数。目录1函数的定义与调用函数概述2
函数参数3变量作用域4递归函数56Python函数式编程7函数的综合应用案例6.2函数的定义与调用在Python语言中,使用关键字def定义函数,每个函数都必须有一个唯一的名称,语法如下:def函数名([形参列表]):
函数体6.2函数的定义与调用函数的定义需要注意如下几点:1.建议使用有意义的名称来清楚表示函数的功能,函数名要符合命名规则:只能包含字母、数字和下划线;不能以数字开头;区分大小写,通常用全小写字母;避免使用保留关键字作为函数名。2.函数名后面必须保留一对圆括号。形参列表在圆括号中声明,并用逗号隔开,也可能为空。3.函数可以无返回值,也可以使用return语句返回值。4.函数定义的第一行中圆括号后面的冒号不能少。5.函数体采用缩进书写规则,相对于def关键字必须保持一定的缩进。6.2函数的定义与调用函数定义完成后,在需要使用该函数时可以调用它。函数的调用是通过使用函数名和括号内传递的参数来完成的。在调用函数时,根据需要可以指定实际传入的参数,即实际参数,简称实参。函数调用的语法如下:函数名([实参列表]):需要注意的是,函数的定义和调用是分离的,函数的名称只是用来标识它的存在,实际的代码执行是在函数被调用时发生的。6.2函数的定义与调用在Python中,参数传递的方式主要有两种:按值传递和按引用传递。按值传递:在按值传递中,函数接收的是参数值的副本,而不是参数本身。对参数的任何修改都只会影响副本,而不会影响原始数据。这意味着在函数内部对参数的修改不会影响到函数外部的数据。在Python中,所有的基本数据类型(如整数、浮点数、字符串、元组等)都是通过值传递的。2.按引用传递:在按引用传递中,函数接收的是参数的引用地址,而不是参数的值。因此,对参数的任何修改都会影响到原始数据。换句话说,在函数内部修改参数就像直接在函数外部修改它一样。在Python中,某些对象类型(如列表、字典和自定义对象)是通过引用传递的。6.2函数的定义与调用例6.1按值传递【参考代码】#6-1.py1 defmodify_value(x):2 x=x+13 print(x)4 5 num=56 modify_value(num)#输出:67 print(num)#输出:5#修改不会影响到原始变量在例6.1中,尽管modify_value函数修改了x的值,但这个修改只对函数内部的x有效,对外部的num变量没有任何影响。6.2函数的定义与调用例6.2按引用传递【参考代码】#6-2.py1 defmodify_list(lst):2 lst.append(4)3 print(lst)4 5 my_list=[1,2,3]6 modify_list(my_list)#输出:[1,2,3,4]#修改会影响到原始列表在例6.2中,modify_list函数修改了传入的列表lst,这个修改直接影响了原始的my_list列表。6.2函数的定义与调用注意:尽管Python中很多对象是通过引用传递的,但变量本身不是通过引用传递的。变量的实质是对象的名称,而不是对象本身。因此,当我们把一个对象赋值给一个变量时,实际上是把这个对象的引用地址赋值给了变量。当我们把一个变量作为参数传递给一个函数时,实际上是把这个变量的引用地址传递给了函数。6.2函数的定义与调用在Python中,可以在函数体内使用return语句为函数指定返回值,且无论return语句出现在函数的什么位置,只要得到执行,就会直接结束函数的执行。当函数中没有return语句时,或者省略了return语句的参数时,将返回None,即返回空值。函数可以有一个或多个返回值,这些返回值可以是任何类型的数据。若要返回多个值,可以使用逗号将它们分隔开,当函数执行完毕后,它会将返回的多个值作为元组返回。在Python中,定义函数时不用预先限定其参数和返回值的类型,Python解释器会根据实参的值自动推断形参类型,也会根据return语句返回的值来确定函数返回值的类型。6.2函数的定义与调用例6.3定义一个函数,欢迎指定姓名的人。【参考代码】#6-3.py1 defgreet(name):2 return"Hello,"+name+"!"3 4 print(greet("Alice"))#输出"Hello,Alice!"6.2函数的定义与调用例6.4定义返回三个数的平均值的函数,并计算12、16和17的平均值。>>>defaverage(a,b,c): return(a+b+c)/3>>>average(12,16,17)15.06.2函数的定义与调用例6.5定义一个函数,接受矩形的长度和宽度两个参数,并返回矩形的面积。【参考代码】#6-5.py1 defcalculate_area(length,width):2 #计算矩形面积3 area=length*width4 returnarea5 #测试函数6 length=5#矩形的长度为57 width=3#矩形的宽度为38 #调用函数并打印结果9 result=calculate_area(length,width)10 print("矩形的面积为:",result)6.2函数的定义与调用例6.6定义打印n个星号的函数,两边填充空格,总宽度为36,并输出20个星号的效果。>>>defstar(n): print(("*"*n).center(36))#函数star无返回值>>>star(20)********************目录1函数的定义与调用函数概述2
函数参数3变量作用域4递归函数56Python函数式编程7函数的综合应用案例6.3 函数参数在定义函数时可以声明函数的参数,即形式参数,简称形参。在调用函数时向形参传递实参。函数可以有多个参数,也可以没有参数,但定义和调用函数时必须在函数名后加一对圆括号。函数可以接受位置参数、默认值参数、关键字参数,和可变参数等不同类型的参数。6.3.1位置参数在函数调用时,实参默认按位置顺序传递形参,按位置传递的参数称为位置参数,这时实参和形参的顺序必须严格一致,并且实参和形参的数量必须相同。6.3.1位置参数例6.7位置参数示例1>>>defdemo(x,y,z): print(x,y,z)>>>demo(1,2,3)123>>>demo(1,3,2)132>>>demo(2,3,4,5)#实参和形参数量必须相同Traceback(mostrecentcalllast):File"<pyshell#62>",line1,in<module>demo(2,3,4,5)TypeError:demo()takes3positionalargumentsbut4weregiven6.3.1位置参数例6.8位置参数示例2【参考代码】#6-8.py1 defadd(a,b):2 returna-b3 4 result=add(12,5)5 print(result)#输出:76.3.2默认值参数可以在定义函数时为形参设置默认值,以便在调用函数时不必提供该参数的值。对于设置了默认值的形参,在调用函数时将会直接使用定义时设置的默认值,另外也可以通过显示赋值来替换默认值。注意在设置默认值参数时,任何一个默认值参数右边不能出现没有默认值的普通位置参数,否则会提示语法错误。6.3.2默认值参数例6.9默认值参数示例1>>>deftimes(x,t=2): print((x*t))>>>times(8)16>>>times(8,3)246.3.2默认值参数例6.10默认值参数示例2【参考代码】#6-10.py1 defgreet(name="World"):2 return"Hello,"+name+"!"3 4 print(greet())#输出"Hello,World!"5 print(greet("Alice"))#输出"Hello,Alice!"6.3.3关键字参数在函数调用时,可以通过参数名称明确指定哪个值传递给哪个参数。按名称指定传入的参数称为关键字参数。关键字参数意义明确,灵活方便,与顺序无关,实参和形参的顺序可以不一致。6.3.3关键字参数例6.11关键字参数示例1>>>defdemo(x,y,z=6): print(x,y,z)
>>>demo(1,2)126>>>demo(x=9,y=1,z=2)912>>>demo(z=5,x=2,y=3)2356.3.3关键字参数例6.12关键字参数示例2【参考代码】#6-12.py1 defgreet(name,message):2 print(f"{message},{name}!")3 4 greet(message="Goodmorning",name="Alice")#输出:Goodmorning,Alice!6.3.4可变参数可变参数允许在调用函数时传递任意数量的参数。在定义函数时,可以通过带星的参数(*parameter1)接收任意多个位置实参并将其放入一个元组中;还可以通过带双星的参数(**parameter2)接收多个关键参数并将其放入字典中。带星和带双星的参数为可变参数,必须位于形参列表的最后位置。6.3.4可变参数例6.13带星的可变参数示例>>>defdemo(*q): print(q)>>>demo(3,6,9)(3,6,9)>>>demo(1,3,5,7,9)(1,3,5,7,9)6.3.4可变参数例6.14带双星的可变参数示例>>>defdemo(**q): forjinq.items(): print(j)>>>demo(a=5,b=1,c=9)('a',5)('b',1)('c',9)6.3.5传递参数时的序列解包在Python中,序列解包是一种非常方便的方式,可以将序列(如列表、元组)中的元素解包并赋值给多个变量。这种方式可以使得代码更加简洁和易读。6.3.5传递参数时的序列解包例6.15基本的序列解包#将元组中的值解包给多个变量>>>t=(1,2,3)a,b,c=tprint(a,b,c)#输出:123#将列表中的值解包给多个变量>>>l=[4,5,6]x,y,z=lprint(x,y,z)#输出:4566.3.5传递参数时的序列解包例6.16交换变量值#使用序列解包交换变量值>>>a,b=1,2a,b=b,aprint(a,b)#输出:21例6.17函数返回多个值#函数返回多个值,使用序列解包接收defget_user_info():return"Alice",25,"alice@"name,age,email=get_user_info()print(name,age,email)#输出:Alice25alice@6.3.5传递参数时的序列解包例6.18部分解包#部分解包,使用占位符_>>>values=(10,20,30,40,50)a,b,*rest=valuesprint(a,b,rest)#输出:1020[30,40,50]例6.19解包嵌套序列#解包嵌套序列>>>data=['Alice',25,(1995,8,15)]name,age,(year,month,day)=dataprint(name,age,year,month,day)#输出:Alice251995815目录1函数的定义与调用函数概述2
函数参数3变量作用域4递归函数56Python函数式编程7函数的综合应用案例6.4 变量作用域变量的作用域是指程序代码能够访问该变量的区域,也就是变量起作用的代码区域。一般根据变量的有效范围将变量分为全局变量和局部变量。此外,还有一些特殊的关键字和语句可以用来处理变量的作用域,比如global、nonlocal等。
局部变量是指在函数内部定义并使用的变量,它只在函数内部有效。
全局变量为能够作用于函数内外的变量。如果一个变量在函数外定义,那么在函数内外都可以访问到该变量,在函数内如果只引用该变量的值而没有修改其值,该变量为全局变量。如果一个变量在函数体内定义,并且使用global关键字声明后,该变量就变成全局变量。6.4 变量作用域
不同作用域内同名变量之间互不影响。如果局部变量和全局变量同名,该局部变量会在自己的作用域内暂时隐藏同名的全局变量。如果想要在函数体内部修改在函数外定义的全局变量的值,需要在定义局部变量时,使用global关键字声明,否则会自动创建新的局部变量。使用内置函数globals()和locals()可以查看并输出局部变量和全局变量列表。
注意:尽管Python允许全局变量和局部变量同名,但在实际开发中不建议这么做,因为这样容易让代码显得混乱。
6.4 变量作用域例6.20变量作用域示例1defdemo1():globala#声明全局变量
a=7#修改全局变量的值
b=8print(a,b)>>>a=6#创建全局变量>>>demo1()78>>>a7
6.4 变量作用域>>>b#局部变量在函数运行结束之后自动删除Traceback(mostrecentcalllast):File"<pyshell#44>",line1,in<module>bNameError:name'b'isnotdefined>>>dela>>>aTraceback(mostrecentcalllast):File"<pyshell#46>",line1,in<module>aNameError:name'a'isnotdefined>>>demo1()78>>>a76.4 变量作用域例6.21变量作用域示例2x=10#全局变量deffunc():y=20#局部变量
print(x)#可以访问全局变量
print(y)#可以访问局部变量func()print(x)#在函数外部也可以访问全局变量#print(y)#这里会报错,因为无法访问局部变量6.4 变量作用域例6.23使用global关键字修改全局变量x=10#全局变量deffunc():globalx#声明要修改的是全局变量
x=20print(x)#输出:20func()print(x)#输出:20,全局变量的值已被修改6.4 变量作用域例6.24使用nonlocal关键字修改嵌套作用域中的变量defouter():x=10#外部函数中的变量
definner():nonlocalx#声明要修改的是外部函数中的变量
x=20print(x)#输出:20inner()print(x)#输出:20,外部函数中的变量的值已被修改outer()目录1函数的定义与调用函数概述2
函数参数3变量作用域4递归函数56Python函数式编程7函数的综合应用案例6.5递归函数递归函数即自调用函数,在函数体内部直接或间接地调用函数自身。利用函数递归可把一个大型的复杂问题层层转化为一个与原来问题本质相同,但规模很小且容易解决或描述的问题。递归函数在计算机科学中是一个非常重要的概念,有助于简化问题、处理重复数据结构、实现分治策略、优化计算资源和提高代码的可读性和可维护性。6.5递归函数递归函数的作用主要体现在以下几个方面:1.简化复杂问题:许多复杂的问题可以通过分解为更小的子问题来解决,而这些子问题又可以通过递归地调用同样的函数来解决。通过将问题分解为更小的部分,递归函数能够将复杂问题简化,使其更容易理解和解决。2.处理重复或循环的数据结构:递归函数特别适合处理重复或循环的数据结构,如数组、列表、树和图等。通过递归地遍历这些数据结构,函数可以处理每一个元素或节点,从而高效地完成数据处理任务。3.实现分治策略:递归函数常常用于实现分治策略,即将一个复杂问题分解为两个或更多相同的子问题,然后递归地解决这些子问题。这种策略在很多算法中都有应用,如快速排序、归并排序和分治算法等。4.优化计算资源:递归函数可以优化计算资源的使用。当一个问题可以被分解为多个重复或类似的子问题时,使用递归函数可以避免重复计算相同的子问题,从而提高计算效率。5.抽象和封装:递归函数提供了一种抽象和封装的方法,使得代码更加简洁和易于理解。通过将复杂的逻辑过程封装在函数内部,递归函数使得代码更加模块化,更易于复用和维护。6.5递归函数
使用递归函数需要注意如下几点:1.每次递归保持问题性质不变。2.必须设置终止条件,保证递归过程可以结束。3.必须保证收敛,每次递归应使问题规模越来越小。4.必须保证内存和运行时间控制在一定范围内,递归的深度不能太大。6.5递归函数
例6.26编写递归函数实现阶乘。【参考代码】#6-24.py1 deffactorial(n):2 ifn==0:3 return14 else:5 returnn*factorial(n-1)6 #测试代码7 foriinrange(0,9):#输出0到9的阶乘8 print(i,'!=',factorial(i))6.5递归函数程序运行结果如下:0!=11!=12!=23!=64!=245!=1206!=7207!=50408!=40320在上面的代码中,我们定义了一个名为factorial的递归函数,它接受一个整数n作为参数,并返回n的阶乘。如果n等于0,函数返回1;否则,函数返回n乘以n-1的阶乘。在递归调用中,我们传递n-1作为新的参数,直到n等于0为止。需要注意的是,递归函数必须有一个或多个基本情况(basecase),以便递归终止。在上面的例子中,基本情况是n==0,此时函数返回1。如果没有基本情况,递归将无限进行下去,导致程序崩溃。6.5递归函数例6.27编写函数,返回第n阶调和数(1+1/2+1/3+…+1/n)的值。【分析】基本思路如下:1.定义一个函数harmonic_number(n),接收一个参数n表示阶数。2.在函数内部,使用递归计算第n阶调和数。3.递归的终止条件是当n等于1时,直接返回1。4.在递归的过程中,累加每个数的倒数,直到计算出第n阶调和数。6.5递归函数【参考代码】1 defharmonic_number(n):2 #递归的基本情况:当n为1时,返回1(因为1的倒数是1)3 ifn==1:4 return1.05 #递归调用:计算n的倒数加上n-1阶调和数6 else:7 return1.0/n+harmonic_number(n-1)8 9 #示例:计算第5阶调和数10 n=511 result=harmonic_number(n)12 print(f"The{n}thharmonicnumberisapproximately:{result}")程序运行结果如下:The5thharmonicnumberisapproximately:2.2833333333333336.5递归函数例6.28斐波那契数列(Fibonaccisequence),又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……,数列从第3项开始,每一项都等于前两项之和。在数学上,斐波纳契数列定义为:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n>1,n∈N)。编写递归函数,实现斐波那契数列。【参考代码】1 deffib(n):2 ifn<=1:3 returnn4 else:5 returnfib(n-2)+fib(n-1)6 #测试代码7 foriinrange(0,10):#输出斐波那契数列的前10项8 print(fib(i),end="")程序运行结果如下:0112358132134目录1函数的定义与调用函数概述2
函数参数3变量作用域4递归函数56Python函数式编程7函数的综合应用案例6.6Python函数式编程
Python中的函数式编程是一种编程范式,它强调函数的纯粹性、不可变性和高阶函数等特性。在Python中,函数式编程可以通过作为对象的函数、lambda表达式、高阶函数、生成器函数等特性来实现。6.6.1作为对象的函数在python语言中函数也是对象,函数对象可以赋值给变量。例6.29作为对象的函数示例#函数可以赋值给变量,作为参数传递,作为返回值等defadd(a,b):returna+bdefsubtract(a,b):returna-boperation=addresult=operation(5,3)#调用add函数print(result)#输出:86.6.2高阶函数
函数对象也可以作为参数传递给函数,还可以作为函数的返回值。参数为函数对象的函数或返回函数对象的函数称为高阶函数,即函数的函数。例6.30高阶函数示例#接受函数作为参数或返回函数的函数就是高阶函数defapply_operation(operation,a,b):returnoperation(a,b)result=apply_operation(add,5,3)print(result)#输出:86.6.3Lambda表达式如果函数的形式比较简单,只需要临时使用函数作为参数传递给其他函数,可使用Lambda表达式声明匿名函数。例如内置函数sorted()和max()的key参数,map()的第一个参数等。虽然也可以使用Lambda表达式定义具名函数,但一般不这样用。Lambda表达式的基本格式如下:
result=lambdaarg1,arg2,arg3…:<expression>其中,result用于调用lambda表达式;arg1等为可选参数,用于指定要传递的参数列表,可以有多个,多个参数之间使用逗号分隔;<expression>为必选语句,用于指定一个实现具体功能的表达式,其结果为匿名函数的返回值。
6.6.3Lambda表达式例6.31计算两数之差。>>>f=lambdax,y:x-y>>>f(9,3)6>>>f(3,9)-66.6.3Lambda表达式例6.32使用lambda表达式作为排序规则。>>>data=[0,3,5,18,16,12,15,123,101,7,99,100]>>>data.sort(key=lambdax:len(str(x)))#按元素转换为字符串后的长度排序,默认升序>>>data[0,3,5,7,18,16,12,15,99,123,101,100]>>>data.sort(key=lambdax:len(str(x)),reverse=True)#降序排序>>>data[123,101,100,18,16,12,15,99,0,3,5,7]例6.33过滤列表,返回元素为偶数的可迭代对象。>>>list(filter(lambdax:x%2==0,range(20)))[0,2,4,6,8,10,12,14,16,18]6.6.4生成器函数生成器函数是一种特殊的函数,它使用yield语句来产生一系列的值。与普通函数不同的是,生成器函数在每次调用yield时会暂停执行并保存当前状态,下次调用时会从上次暂停的地方继续执行。例6.34生成器函数示例defcountdown(n):whilen>0:yieldnn-=1foriincountdown(5):print(i)#依次输出5,4,3,2,16.6.4生成器函数例6.35无限序列生成器示例definfinite_sequence():num=0whileTrue:yieldnumnum+=1foriininfinite_sequence():print(i)#会无限输出自然数序列例6.36生成器表达式示例>>>gen=(x**2forxinrange(5))print(list(gen))#输出[0,1,4,9,16]6.6.5操作符函数在Python中,operator模块提供了一组对应于内置操作符的函数,可以用于实现相同的操作。这些函数可以在不直接使用操作符的情况下进行操作,这在某些情况下会更加灵活和直观。1.比较操作符operator模块提供了比较操作符的函数,包括lt(lessthan),le(lessthanorequal),eq(equal),ne(notequal),ge(greaterthanorequal),gt(greaterthan)。例6.37比较操作符示例importoperator#使用比较操作符函数print(operator.lt(3,5))#输出:Trueprint(operator.eq(3,5))#输出:False6.6.5操作符函数2.算术操作符operator模块还提供了算术操作符的函数,包括add(加法),sub(减法),mul(乘法),truediv(真除法),floordiv(整除),mod(取模),pow(幂运算)。例6.38算术操作符示例#使用算术操作符函数print(operator.add(3,5))#输出:8print(operator.truediv(10,3))#输出:3.33333333333333353.逻辑操作符operator模块还提供了逻辑操作符的函数,包括and_(逻辑与),or_(逻辑或),not_(逻辑非)。例6.39逻辑操作符示例#使用逻辑操作符函数print(operator.and_(True,False))#输出:Falseprint(operator.not_(True))#输出:False6.6.5操作符函数4.位操作符operator模块也包含了位操作符的函数,例如and_(按位与),or_(按位或),xor(按位异或),lshift(左移),rshift(右移)。例6.40位操作符示例#使用位操作符函数print(operator.xor(0b1010,0b1100))#输出:6print(operator.lshift(1,2))#输出:45.其他操作符函数除了上述提到的操作符函数之外,operator模块还包含了一些其他有用的函数,比如itemgetter用于获取对象的某个索引或键对应的值,attrgetter用于获取对象的属性值,methodcaller用于调用对象的方法等。6.6.6装饰器函数装饰器允许在不修改原始函数代码的情况下,对函数的行为进行扩展或修改。装饰器本质上是一个函数,它接受一个函数作为输入,并返回一个新的函数作为输出。例6.41装饰器函数示例:defmy_decorator(func):defwrapper():print("Somethingishappeningbeforethefunctioniscalled.")func()print("Somethingishappeningafterthefunctioniscalled.")returnwrapper@my_decoratordefsay_hello():print("Hello!")say_hello()目录1函数的定义与调用函数概述2
函数参数3变量作用域4递归函数56Python函数式编程7函数的综合应用案例6.7函数的综合应用案例例6.42编写一个函数,接受一个整数作为参数,判断该数是否为素数,并返回True或False。【分析】素数是一个大于1的自然数,除了1和它本身以外不再有其他因数。我们可以通过遍历2到n之间的所有数,判断是否存在n的因数来实现这个判断。具体步骤如下:1.初始化一个布尔变量is_prime为True,表示当前数字是素数。2.从2开始遍历到n的平方根,检查是否存在n的因数。如果存在因数,则将is_prime设置为False,表示当前数字不是素数。3.返回is_prime的值。6.7函数的综合应用案例【参考代码】1 defis_prime(n):2 ifn<=1:#1和0不是素数3 returnFalse4 ifn==2:#2是素数5 returnTrue6 ifn%2==0:#其他偶数(除2外)不是素数7 returnFalse8 #判断奇数是否为素数9 foriinrange(3,int(n**0.5)+1,2):#只遍历到n的平方根,并且只遍历奇数10 ifn%i==0:11 returnFalse12 returnTrue使用示例:print(is_prime(7))#True,7是素数print(is_prime(10))#False,10不是素数6.7函数的综合应用案例例6.43编写一个函数,接受两个整数作为参数,并返回它们的最大公约数和最小公倍数。【分析】我们可以使用欧几里得算法(也称为辗转相除法)来找到两个数的最大公约数(GCD),然后使用这个结果来找到最小公倍数(LCM)。最大公约数和最小公倍数之间有一个重要的关系:两数的乘积等于它们的最大公约数和最小公倍数的乘积。即:a*b=GCD(a,b)*LCM(a,b)。6.7函数的综合应用案例以下是Python代码实现:defgcd_lcm(a,b):#使用欧几里得算法求最大公约数defgcd(x,y):whiley!=0:x,y=y,x%yreturnx
#使用最大公约数求最小公倍数lcm=(a*b)//gcd(a,b)returngcd(a,b),lcm6.7函数的综合应用案例例6.44
编写函数,打印99乘法表。【参考代码】方法一:使用嵌套循环defprint_multiplication_table():foriinrange(1,10):forjinrange(1,10):print(f'{i}x{j}={i*j}',end='\t')print()#换行#调用函数打印99乘法表print_multiplication_table()6.7函数的综合应用案例方法二:使用字符串格式化defprint_multiplication_table():foriinrange(1,10):row='\t'.join([f'{i}x{j}={i*j}'forjinrange(1,10)])print(row)#调用函数打印99乘法表print_multiplication_table()6.7函数的综合应用案例例6.45编写函数,模拟猜数游戏。【分析】猜数游戏是一个经典的互动游戏,程序会随机生成一个1到100之间的整数,然后要求玩家通过输入来猜测这个数字,直到猜中为止。程序会根据玩家的猜测给出提示,告诉玩家猜的数字是偏大还是偏小。基本思路如下:1.使用Python的random模块生成一个1到100之间的随机数作为目标数字。2.使用循环结构,让玩家可以多次输入猜测的数字,并根据输入结果给出相应的提示。3.当玩家猜中目标数字时,输出祝贺信息,并结束游戏。6.7函数的综合应用案例
【参考代码】1 importrandom2 3 defguess_number_game():4 target_number=random.randint(1,100)5 print("欢迎参加猜数字游戏!我已经想好了一个1到100之间的整数,你来猜猜是多少?")6 7 whileTrue:8 guess=int(input("请输入你猜测的数字:"))9 ifguess<target_number:10 print("猜的有点小,再试试大一点的数字吧。")11 elifguess>target_number:12 print("猜的有点大,再试试小一点的数字吧。")13 else:14 print("恭喜你,猜对了!答案就是",target_number)15 break16 17 guess_number_game()6.7函数的综合应用案例例6.46编写函数,模拟井字棋游戏。【分析】井字棋是一种两人轮流下棋的游戏,棋盘是一个3x3的方格,玩家需要在棋盘上落子,先在横向、纵向或对角线上连成一条直线的玩家获胜。如果棋盘填满且没有玩家连成一条直线,则游戏为平局。基本思路如下:1.创建一个3x3的棋盘,用二维列表来表示,初始化为空格。2.编写函数来显示棋盘。3.编写函数来接受玩家输入的坐标,并在棋盘上落子。4.编写函数来检查游戏是否结束,即检查是否有玩家获胜或者游戏为平局。6.7函数的综合应用案例【参考代码】
1 defprint_board(board):2 forrowinboard:3 print("|".join(row))4 print("---------")5 6 defcheck_winner(board,player):7 #检查横向8 forrowinboard:9 ifall([cell==playerforcellinrow]):10 returnTrue11 #检查纵向12 forcolinrange(3):13 ifall([board[row][col]==playerforrowinrange(3)]):14 returnTrue15 #检查对角线6.7函数的综合应用案例16 ifall([board[i][i]==playerforiinrange(3)])orall([board[i][2-i]==playerforiinrange(3)]):17 returnTrue18 returnFalse19 20 deftic_tac_toe():21 board=[[""for_inrange(3)]for_inrange(3)]22 players=["X","O"]23 turn=024 25 print("欢迎来到井字棋游戏!")26 print_board(board)27 28 whileTrue:29 player=players[turn%2]30 print(f"轮到玩家{player}下棋")31 row=int(input("请输入行号(0-2):"))32 col=int(input("请输入列号(0-2):"))33 6.7函数的综合应用案例34 ifboard[row][col]=="":35 board[row][col]=player36 print_board(board)37 ifcheck_winner(board,player):38 print(f"玩家{player}获胜!")39 break40 ifall(all(cell!=""forcellinrow)forrowinboard):41 print("平局!")42 break43 turn+=144 else:45 print("该位置已经有棋子,请重新输入坐标。")46 47 tic_tac_toe()6.7函数的综合应用案例例6.47编写函数,实现冒泡排序算法。【分析】冒泡排序算法是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来,直到没有元素需要交换,排序完成。基本思路如下:1.从第一个元素开始,依次比较相邻的两个元素,如果顺序不对则交换它们的位置,将较大的元素交换到后面。2.经过一轮比较后,最大的元素将被交换到数组末尾。3.重复以上步骤,直到所有元素都按照从小到大的顺序排列。6.7函数的综合应用案例【参考代码】1 defbubble_sort(arr):2 n=len(arr)3 foriinrange(n):4 #标记本轮是否有元素交换5 swapped=False6 forjinrange(0,n-i-1):7 ifarr[j]>arr[j+1]:8 arr[j],arr[j+1]=arr[j+1],arr[j]9 swapped=True10 #如果本轮没有元素交换,说明已经有序,可以提前结束11 ifnotswapped:12 break13 returnarr14 6.7函数的综合应用案例
15 #测试16 arr=[64,34,25,12,22,11,90]17 sorted_arr=bubble_sort(arr)18 print("排序后的数组:",sorted_arr)6.7函数的综合应用案例例6.48编写函数,实现二分查找算法。【分析】二分查找算法是一种在有序数组中查找特定元素的算法。它通过将待查找区间的中间元素与目标元素进行比较,从而将待查找区间缩小一半,直到找到目标元素或者确定目标元素不存在。基本思路如下:1.确定查找区间的起始和结束位置,分别为left和right。2.在每一步中,计算中间位置mid,并将目标元素与arr[mid]进行比较。3.如果目标元素等于arr[mid],则找到目标元素,返回mid。4.如果目标元素小于arr[mid],则将查找区间缩小为left到mid-1。5.如果目标元素大于arr[mid],则将查找区间缩小为mid+1到right。6.重复步骤2-5,直到找到目标元素或者确定目标元素不存在。6.7函数的综合应用案例【参考代码】1 defbinary_search(arr,target):2 left,right=0,len(arr)-13 whileleft<=right:4 mid=(left+right)//25 ifarr[mid]==target:6 returnmid7 elifarr[mid]<target:8 left=mid+19 else:10 right=mid-111 return-1#目标元素不存在12 6.7函数的综合应用案例
13 #测试14 arr=[2,3,4,10,40]15 target=1016 result=binary_search(arr,target)17 ifresult!=-1:18 print(f"元素在索引{result}处")19 else:20 print("元素不在数组中")6.7函数的综合应用案例例6.49编写函数,实现选择排序算法。【分析】选择排序算法是一种简单直观的排序算法,它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余未排序元素中继续寻找最小(或最大)元素,放到已排序序列的末尾。基本思路:1.遍历数组,找到最小的元素,并将其与第一个元素交换位置。2.在剩余的未排序部分中,继续找到最小的元素,并将其与第二个元素交换位置。3.重复以上步骤,直到所有元素都按照从小到大的顺序排列。6.7函数的综合应用案例【参考代码】defselection_sort(arr):n=len(arr)foriinrange(n-1):min_index=iforjinrange(i+1,n):ifarr[j]<arr[min_index]:min_index=jarr[i],arr[min_index]=arr[min_index],arr[i]returnarr#测试arr=[64,25,12,22,11]sorted_arr=selection_sort(arr)print("排序后的数组:",sorted_arr)6.7函数的综合应用案例例6.50编写函数,实现合并排序算法。【分析】合并排序算法(MergeSort)是一种分治策略的排序算法,它将待排序的数组分成两个相等大小的子数组,然后递归地对子数组进行排序,最后将已排序的子数组合并成一个有序数组。基本思路是将一个大问题分解成两个小问题,分别解决后再将它们的解合并起来。基本思路如下:1.将待排序的数组分为两个子数组,直到每个子数组只包含一个元素。2.递归地对每个子数组进行排序。3.合并两个已排序的子数组,生成一个新的已排序数组。6.7函数的综合应用案例【参考代码】1 defmerge_sort(arr):2 iflen(arr)<=1:3 returnarr4 5 #将数组分为两半6 mid=len(arr)//27 left=arr[:mid]8 right=arr[mid:]9 10 #递归地对每个子数组进行排序11 left=merge_sort(left)12 right=merge_sort(right)13 14 #合并两个已排序的子数组15 returnmerge(left,right)16 6.7函数的综合应用案例17 defmerge(left,right):18 result=[]19 i=j=020 21 #按顺序比较左右两个数组的元素,并合并22 whilei<len(left)andj<len(right):23 ifleft[i]<right[j]:24 result.append(left[i])25 i+=126 else:27 result.append(right[j])28 j+=129 6.7函数的综合应用案例
30 #将剩余的元素添加到结果数组中31 result.extend(left[i:])32 result.extend(right[j:])33 34 returnresult35 36 #测试37 arr=[38,27,43,3,9,82,10]38 sorted_arr=merge_sort(arr)39 print("排序后的数组:",sorted_arr)6.7函数的综合应用案例例6.51
编写函数,计算任意位数的黑洞数。【分析】黑洞数(也称为陨石数或Kaprekar常数)是一个有趣的数学现象,以任意一个正整数,重新排列其数字构成最大数和最小数,然后用最大数减去最小数,重复这个过程。最终会得到一个稳定的值,称为黑洞数。例如,以1234开始,得到的序列为4321-1234=3087,8730-378=8352,8532-2358=6174,7641-1467=6174,最终稳定在6174。基本思路:1.定义一个函数black_hole_number,接受一个正整数作为参数。2.在函数内部,编写循环来重复执行以下步骤:o将输入的整数转换为字符串,然后分别按升序和降序排列其数字,得到最大数和最小数。o计算最大数减去最小数,得到新的整数。o如果新的整数等于之前的整数,则停止循环,返回这个稳定的值作为黑洞数。6.7函数的综合应用案例【参考代码】defblack_hole_number(num):whileTrue:#将整数转换为字符串,并按升序和降序排列数字num_str=str(num)max_num=int(''.join(sorted(num_str,reverse=True)))min_num=int(''.join(sorted(num_str)))
#计算差值new_num=max_num-min_num
#如果新的整数等于之前的整数,则停止循环,返回这个稳定的值ifnew_num==num:returnnew_numelse:num=new_num6.7函数的综合应用案例#测试input_num=1234result=black_hole_number(input_num)print(f"Theblackholenumberfor{input_num}is{result}")6.7函数的综合应用案例例6.52编写函数,实现汉诺塔问题。【分析】汉诺塔问题是一个经典的问题。汉诺塔(HanoiTower),又称河内塔,源于印度的一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。后来就演变成汉诺塔益智游戏:1.有三根柱子A、B、C,A柱上有n个圆盘,且大的在小的下面。2.每次只能移动一个圆盘,小盘只能放在大盘上面。3.要把A柱上的圆盘移动到C柱上。基本思路如下:1.当A柱上只有一个圆盘时,直接将该圆盘从A柱移动到C柱。2.当A柱上有n个圆盘时,将前n-1个圆盘从A柱移动到B柱,再将第n个圆盘从A柱移动到C柱,最后将前n-1个圆盘从B柱移动到C柱。假设3根柱子的编号分别为x、y、z,汉诺塔的层数为n,也就是说柱子x上有n个圆盘。定义函数hano(n,x,y,z),表示把n个圆盘从柱子x移动到柱子z,过程中可以经由柱子y。6.7函数的综合应用案例【参考代码】1 defhano(n,x,y,z):2 ifn==1:3 print(x,"->",z)4 #柱子x上只有一个圆盘,直接将圆盘从柱子x移动到柱子z上5 else:6 #将n-1个盘子从x->y7 hano(n-1,x,z,y)8 #将剩余的最后一个盘子从x->z9 print(x,"->",z)10 #将剩余的n-1个盘子从y->z11 hano(n-1,y,x,z)12 n=int(input("请输入汉诺塔的层数:"))13 hano(n,"A","B","C")6.7函数的综合应用案例例6.53编写函数,求解n皇后问题。【分析】n皇后问题要求在n×n格的棋盘上放置n个彼此不受攻击的皇后。根据国际象棋的规则,n皇后问题等价于在n×n格的棋盘上放置n个皇后,使得任意两个皇后都不在同一行、同一列或同一斜线上。采用回溯算法求解,基本思路如下:1.创建一个空字符串,用于存储每一行的皇后位置。2.遍历每一行,从第一行开始放置皇后。3.在每一行中,遍历每一个位置,尝试放置皇后。4.如果放置成功,则递归地放置下一行的皇后。5.如果放置失败,则回溯到上一个位置,继续尝试其他位置。6.如果所有皇后都放置成功,则输出结果。6.7函数的综合应用案例【参考代码】defsolveNQueens(n):defcan_place(row,col): #检查当前位置(row,col)是否安全,即不存在冲突 foriinrange(row): ifboard[i]==color\ board[i]-i==col-rowor\ board[i]+i==col+row: returnFalsereturnTrue
defplace_queen(row,n): ifrow==n: result.append(board[:]) returnforcolinrange(n): ifcan_place(row,col): board[row]=colplace_queen(row+1,n) board[row]=0#回溯,将当前位置重置为0
result=[]#存储所有解的列表board=[0]*n#存储每一行皇后的列位置,初始值为0,表示该位置不可放置皇后place_queen(0,n)#从第一行开始放置皇后returnresult#返回所有解的列表print("测试结果:")forninrange(1,6):solutions=solveNQueens(n)print(f"n={n}:{len(solutions)}个解决方案")ifs
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年交通安全知识模拟考试题库
- 2026年高三生物必修一第七章生物技术测试卷
- 2026年计算机二级C语言编程模拟题库
- 2026-2030青年太阳镜行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 2026-2030中国钠离子浓度计行业前景调研与未来发展策略分析研究报告
- 2026年山海经地理知识测试卷
- 2026年交通安全法规与驾驶操作模拟卷
- 2026年山西省部编版初中物理九年级上册第4章应用题专项训练
- 2026-2030飞机绝缘行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 2026-2030中国丙酮酸乙酯市场运行趋势及未来竞争格局展望研究报告
- cad二维练习图大全
- 心脏外科围手术期液体管理
- 2025年邮政四级副干部竞聘笔试考试题及答案
- 电销培训案例欣赏
- 2025-2030中国心理咨询机构市场经营模式及消费前景预测研究报告
- 2026版水利三类人员专职安全员C证试题题库含答案
- 2026年拔尖人才考试试题数学
- 民航安检业务知识课件
- 12345话务员培训教学课件
- 2026年注册安全工程师题库300道及参考答案【新】
- 肺栓塞患者的麻醉管理
评论
0/150
提交评论