第八章 函数-1
到现在为止,我们学完了Python的基础知识和程序的三种控制结构,函数这一章是帮助我们向更高的程序设计阶段进发,一般说来,所有的程序设计语言里都有函数(有的语言称为模块),这是为什么呢?
想想第三章我们介绍了内置函数,为啥要有内置函数呢?因为这些功能经常要用到,所以编写成一个函数供大家使用。但是这些函数都是通用功能,比如数学函数、字符串函数等等。不同领域常用功能不同,所以不同专业需要自己的函数,我们编写完函数之后还可以给其他人用,这就是代码复用。其实我们自己编写程序也应该是把写过的代码保存好,万一以后用到呢?梦想还是要有的,万一实现了呢。
8.1 函数定义
函数是一种仅在调用时运行的代码块。可以将数据(称为参数)传递到函数中,函数可以把数据作为结果返回。具体的语法如下:
def 函数名([参数列表]):
#实现特定功能的多行代码
[return [返回值]]
参数列表是用逗号分隔的标识符,[ ]表示括起来的部分可以有也可以没有,所以参数可以没有,返回值可以没有,不带表达式的return相当于返回 none。
我们先看一个例子,输出一行星号。
def displayStar():
print("**********************")
这里函数名为displayStar,函数没有参数,没有返回值。函数功能为打印一行星号的语句。
函数头为def displayStar():
函数体为函数头部下方有缩进的部分,这里只有一条语句print("**********************")。
在PyCharm里输入上述函数之后运行程序,没有任何输出结果,因为displayStar函数没有被调用,所以不会执行函数里的函数体代码。
学过函数之后,我们需要学会定义一个main()函数,在main函数中编写代码调用定义好的函数,然后在程序中调用main函数。这样程序执行就会先执行main函数,如果main函数中调用了其它函数,则程序转向调用的函数执行该函数的函数体,调用结束之后,返回到调用的位置继续执行下面的代码。程序的执行过程总结一下就是:当程序调用一个函数时,程序控制权就会转移到被调用的函数上。当执行完函数的返回语句或执行到函数结束时,被调用函数就会将程序控制权交还给调用者。
为了执行displayStar函数,我们还需要编写main函数,在main函数中调用displayStar函数,具体代码如下:
def displayStar():
print("displayStar begin")
print("**********************")
print("displayStar end")
def main():
print("main begin")
displayStar()
print("main end")
main()
运行程序结果为:
main begin
displayStar begin
**********************
displayStar end
main end
程序执行过程如下图所示:

根据图示,结合程序运行结果,大家可以分析一下程序的执行过程。在这个例子的基础上,我们再看一个有参数的例子,改写上面代码如下:
def displayStar(n):
for i in range(n):
print("**********************")
def main():
row=int(input("行数:"))
displayStar(row)
main()
运行程序结果为:
行数:4
**********************
**********************
**********************
**********************
程序实现了通过获取输入行值,输出相应行数的星号。
清楚了上面的例子,我们再看一个函数例子,编程实现求指定区间的所有整数的和。如指定1-10,则计算出1+2+3+……+10的和。自己先试着编写一下代码然后再往下看吧。
哎呀,我不会写呀!没有关系,不用函数会做不?不就是计算累加和吗,不难,如下:
s=0
x,y =eval(input("区间:"))
for i in range(x,y+1):
s=s+i
print(s)
好下面我们需要把它改成函数方式实现。⑴先定义函数:def关键字,函数名,括号冒号都会写
def n1n2Sum(n1,n2): #函数名n1n2Sum求表示n1、n2之间的和。
函数头搞定,下面看函数体。函数体不就是已知n1、n2,计算n1、n2之间所有整数的和。参考上面的编写代码如下
s=0 #这个千万不要忘了
for i in range(n1,n2+1):
s=s+i
print(s)
所以函数定义完了,下面这样,其实我就是从上复制过来的,但是要注意缩进:
def n1n2Sum(n1,n2): #函数名表示n1、n2之间的和。
s=0 #这个千万不要忘了
for i in range(n1,n2+1):
s=s+i
print(s)
接下来⑵定义main函数,在main里调用上面的函数(当然可以不定义main函数,但是定义main函数程序的可读性好,代码规范)。函数调用的时候确保参数有确定值,所以需要通过input函数获取用户输入。当然可以直接指定一个值,如n1n2Sum(1,10),但是程序运行就只能计算1-10的整数和,不灵活,不方便。
def main():
x, y = eval(input("区间:"))
n1n2Sum(x,y) #调用函数n1n2Sum
⑶程序中调用main函数,简单:main()
Over,如果不熟练的话,请再练习n遍,(n>=3),送你编程秘籍:无他,唯手熟尔!
我们再看看刚才的代码:
def n1n2Sum(n1,n2):
s=0
for i in range(n1,n2+1):
s=s+i
print(s)
def main():
x, y = eval(input("区间:"))
n1n2Sum(x,y)
main()
假设我的要求改了(开发软件过程中,用户需求就是会变来变去的,所以用户需求变更位于惹毛程序员的十件事前列),我想输出的2倍,简单,函数n1n2Sum 的print(s)改成print(2*s)不就行啦。是的,可以但是代码质量不高,一般一个函数只完成一个功能,所以更好的方法是我们把函数定义成有返回值的,这样保证函数的功能就是求指定区间所有整数的和。所以代码改成下面这样的:
def n1n2Sum(n1,n2):
s=0
for i in range(n1,n2+1):
s=s+i
return s
def main():
x, y = eval(input("区间:"))
s=n1n2Sum(x,y)
print(2*s)
main()
我们看一下n1n2Sum(n1,n2)函数的功能,实现n1-n2之间所有整数的和。可以这样理解,对于这个问题,已知两个整数n1,n2,求这两个数之间所有整数的和。已知一般可以作为函数参数,求的结果可以作为返回值,函数体是具体的功能。所以使用函数编程时,要考虑已知(作为函数的参数)和求的结果(作为函数返回值)这两部分,然后具体问题具体分析,再完成函数体部分。
我们再来一个例子:求两个整数的最大公约数和最小公倍数,最大公约数使用数学家的算法,最小公倍数使用普通人的办法。先看最大公约数的算法:
第 1 步:比较 A 和 B 这两个数,将 A 设置为较大的数,B 为较小的数。
第 2 步:A 除以 B,得余数 R(Remainder)。
第 3 步:如果 R=0,则最大公约数就是 B;否则将 B 赋值给 A,R赋值给 B,重复进行前两步。
按照上述算法,定义函数gcd,已知为 ,求的是 。所以gcd函数的参数为两个整数a,b,返回值为a,b的最大公约数。函数体呢?参见上述算法描述呀!
第 1 步:比较 A 和 B 这两个数,将 A 设置为较大的数,B 为较小的数。
对应的Python表示为:
第 2 步:A 除以 B,得余数 R(Remainder)。
对应的Python表示为:
第 3 步:如果 R=0,则最大公约数就是 B;否则将 B 赋值给 A,R赋值给 B,重复进行前两步。
对应的Python表示为:
实际上,最后一步需要认真思考:①要使用循环实现而不是选择操作,因为有重复进行 ②什么情况下执行循环,或者说循环条件怎么写。否则应该表达为R!=0。提示到此结束,编程吧,少年!
def gcd( a , b ):
#第 1 步:比较 A 和 B 这两个数,将 A 设置为较大的数,B 为较小的数。
if a<b:
a,b=b,a
#第2步:A 除以 B,得余数 R(Remainder)。
r= a % b
#第3步:如果R=0,则最大公约数就是 B;否则将 B 赋值给 A,R赋值给 B,重复进行前两步。
while r != 0:
a = b
b = r
r = a % b
return b
def main():
x, y = eval(input("x,y:"))
print(gcd(x,y))
main()
求最小公倍数就是普通人的思维方法。首先明确一点,两个数的最小公倍数值最大的可能是这两个数的乘积(似乎有点绕,我居然没有把自己绕进去,厉害了哈),我们需要让一个循环变量从这两个数中的(大值,小值)开始向这两个数的乘积方向依次加1试一下这个循环变量是否能够整除这两个数(自己思考并且圈一下前面括号里的答案),一直找到满足能够整除这两个数的数为止(为止就是结束,结束在循环里就是break),这时这个数就是这两个数的最小公倍数,我需要回去推敲一下前面写的对不对(大体思路是对的,修改了一下措辞)。实际上求最大公约数也可以使用类似的方法,因为我们都是普通人,暂时不能想出数学家提供的方法,反正我真想不出来。试着把上面求最小公倍数的方法修改一下,改成求最大公约数。还是先编程做完最小公倍数,然后再考虑下一个最大公约数问题吧。好啦,编程去喽!
def lcm( a , b ):
xb=a*b #思考一下这行的意义何在
if a<b:
a,b=b,a
for i in range(a,a*b+1):
if i % a == 0 and i % b == 0:
xb = i
break
return xb
def main():
x, y = eval(input("x,y:"))
print(lcm(x,y))
main()
#思考一下这行的意义何在
这个问题如果自己理解不了,上课时来问我吧!
接下来我们改上面的方法求最大公约数。
两个数的最小公倍(此处改成 大公约 )数值最大(此处改成 )的可能是这两个数的乘积(此处改成 ),我们需要让一个循环变量从这两个数中的(大值,小值)开始向1方向依次减1试一下这两个数是否能够整除这个循环变量(自己思考并且圈一下前面括号里的答案),一直找到满足能够整除这个循环变量的数为止(为止就是结束,结束在循环里就是break),这时这个数就是这两个数的最大公约数。好啦,编程去喽!
def gcd( a , b ):
dy=1 #思考一下这行的意义何在
if a<b:
a,b=b,a
for i in range(b,0,-1):
if a % i == 0 and b % i == 0:
dy = i
break
return dy
def main():
x, y = eval(input("x,y:"))
print(gcd(x,y))
main()
实际上,我还真有一个捷径,悄悄告诉你:两个数的乘积等于这两个数的最大公约数和最小公倍数的乘积。这个有用吗?当然了,如果写好了求最大公约数的函数gcd(x,y), 那么lcm(x,y)=x*y/ gcd(x,y)。