1.2.1 python中的函数

python函数

       函数用于在程序中分离不同的任务;函数允许程序的控制在调用代码和函数代码之间切换

函数功能

(1)实现结构化程序设计。通过把程序分割为不同的功能模块,可以实现自顶向下的结构化设计
(2)减少程序的复杂度。简化程序的结构,提高程序的可阅读性
(3)实现代码的复用。一次定义多次调用,实现代码的可重用性
(4)提高代码的质量。实现分割后子任务的代码相对简单,易于开发、调试、修改和维护
(5)协作开发。大型项目分割成不同的子任务后,团队多人可以分工合作,同时进行协作开发
(6)实现特殊功能。递归函数可以实现许多复杂的算法

函数分类

  • (1)内置函数。Python语言内置了若干常用的函数,例如abs()、len()等等,在程序中可以直接使用

  • (2)标准库函数。Python语言安装程序同时会安装若干标准库,例如math、random等等。通过import语句,可以导入标准库,然后使用其中定义的函数

  • (3)第三方库函数。Python社区提供了许多其他高质量的库,如Python图像库等等。下载安装这些库后,通过import语句,可以导入库,然后使用其中定义的函数

  • (4)用户自定义函数。本章将详细讨论函数的定义和调用方法

函数声明与调用

语法:

def 函数名(参数1,参数2......):          函数体


【例1】函数创建示例1:定义返回两个数平均值的函数

def my_average(number1, number2):           return (number1+number2)/2

【例2】函数创建示例2:定义打印n个星号的无返回值的函数

def print_star(n):        print(("*"*n).center(50))    #打印n个星号,两边填充空格,总宽度50

 

思考

Q:函数创建示例3:定义计算并返回第n阶调和数(1 + 1/2 + 1/3 + … + 1/n)的函数
R:参考答案:

def harmonic(n):  #计算n阶调和数(1 + 1/2 + 1/3 + … + 1/n)       total = 0.0       for i in range(1, n+1):               total += 1.0 / i       return total

 

函数调用

语法:

函数名([实参列表])

示例:基于思考题声明的函数进行调用

 

#因为有返回值,所以可以通过声明变量进行赋值或者直接print输出即可get_result=harmonic(10)  #则表示的hi计算1+1/2+......+1/10print(get_result)

参数的传递

形式参数和实际参数

  • 声明函数时所声明的参数,即为形式参数,简称形参

  • 调用函数时,提供函数所需要的参数的值,即为实际参数,简称实参

  • 【例1】形式参数和实际参数示例(my_max1.py)

def my_max1(a, b):   #此处声明的a,b则为形式参数if a > b: print(a, '>', b)   elif a == b: print(a, '=', b)   else: print(a, '<', b)my_max1(1, 2)   #此时调用函数传入的1,2为实际参数x = 11; y = 8my_max1(x, y)   #此处的x,y也为实际参数my_max1(1)      #因为要求传入a,b两个位置参数,此时只传入一个参数则会报错,缺少一个参数b

 

传递不可变对象引用

如果函数体中修改对象的值,其结果实际上是创建了一个新的对象
【例1】传递不可变对象的引用示例(inc1.py):错误的递增函数

i=100def inc(j,n):       j += ninc(i,10)print(i)

i的初始值为100,当调用函数inc(i,10)后,在函数体内,执行了"i+=10"语句,在函数体内的i编程了110.但是,当函数调用完毕返回主程序,i的值仍然为100,因为整数i是不可变对象,而在Python语言中,一个函数不能改变一个不可变对象(例如:整数、浮点数、布尔值或字符串的值)的值(即函数无法产生副作用)

思考

Q:如何对传递不可变对象例题1实现正确的递增函数
R:参考结果:

i=100def inc(j,n):       j += n       return ji =inc(i,10)print(i)

 

传递可变对象引用

调用函数时,如果传递的是可变对象(例如:list对象)的引用,则函数体中可以直接修改对象的值
【例1】传递可变对象引用的函数示例1:定义一个可以交换给定列表中两个指定下标的元素值的函数​​​​​​​

def exchange(a, i, j):       temp = a[i]       a[i] = a[j]       a[j] = temp

 

可选参数

在声明函数时,如果希望函数的一些参数是可选的,可以在声明函数时为这些参数指定默认值调用该函数时,如果没有传入对应的实参值,则函数使用声明时指定的默认参数值
【例1】可选参数示例(my_sum1.py):基于期中成绩和期末成绩,按照指定的权重计算总评成绩​​​​​​​

def my_sum1(mid_score, end_score, mid_rate = 0.4):  #期中成绩、期末成绩、期中成绩权重    #基于期中成绩、期末成绩和权重计算总评成绩       score = mid_score * mid_rate + end_score * (1 - mid_rate)        print(format(score, '.2f'))  #输出总评成绩,保留2位小数my_sum1(88, 79)            #期中成绩权重为默认的40%my_sum1(88, 79, 0.5)     #期中成绩权重设置为50%

 

位置参数和命名参数

  • 函数调用时,实参默认按位置顺序传递形参。按位置传递的参数称之为位置参数

  • 函数调用时,也可以通过名称(关键字)指定传入的参数,例如:my_max1(a=1, b=2); my_max1(b=2, a=1)

  • 按名称指定传入的参数称为命名参数,也称之为关键字参数。使用关键字参数具有三个优点:参数按名称意义明确;传递的参数与顺序无关;如果有多个可选参数,则可以选择指定某个参数值

  • 在带星号的参数后面声明的参数强制为命名参数,如果这些参数没有默认值,且调用时必须使用命名参数赋值,则会引发错误

  • 如果不需要带星号的参数,只需要强制命名参数,则可以简单地使用一个星号

可变参数

  • 在声明函数时,通过带星的参数,如* param1,允许向函数传递可变数量的实参。调用函数时,从那一点后所有的参数被收集为一个元组

  • 在声明函数时,也可以通过带双星的参数,如** param2,允许向函数传递可变数量的实参。调用函数时,从那一点后所有的参数被收集为一个字典

  • 带星或双星的参数必须位于形参列表的最后位置
    【例1】可变参数示例1(my_sumVarArgs1.py)。利用带星的参数计算各数字累加和

def my_sum3(a, b, *c):          #各数字累加和       total = a + b   for n in c:              total = total + n   return totalprint(my_sum3(1, 2))            #计算1+2print(my_sum3(1, 2, 3, 4, 5))      #计算1+2+3+4+5print(my_sum3(1, 2, 3, 4, 5, 6, 7))  #计算1+2+3+4+5+6+7

 

函数返回值

  • return语句和函数返回值

  • 【例1】函数的返回值示例(my_max.py)。编写函数,利用return语句返回函数值,求若干数中的最大值

def my_max(a, b, *c): #求若干数中的最大值       max_value = a  #假设第一个数为最大值       if max_value < b: #如果最大值小于b,则b为最大值               max_value = b       for n in c:      #循环迭代c中每个元素n,如果最大值小于n,则n为最大值               if max_value < n:                       max_value = n       return max_value  #利用return语句返回最大值#测试代码print(my_max(1, 2))         #求(1, 2)中的最大值print(my_max(1, 7, 11, 2, 5))  #求(1, 7, 11, 2, 5)中的最大值

 

多条return语句

  • return语句可以放置在函数中任何位置,当执行到第一个return语句时,程序返回到调用程序

  • 【例1】判断素数(prime.py)。先编制一个判断一个数是否为素数的函数,然后编写测试代码,判断并输出1~99中的素数

def is_prime(n):   if n < 2: return False  #如果n小于2,返回False       i = 2   while i*i <= n:       #一旦n能够被2~   中的任意整数整除,n就不是素数,返回False       if n % i == 0: return False                i += 1   return True#测试代码for i in range(100):  #判断并输出1~99中的素数,以空格分隔   if is_prime(i):print(i, end=' ')

 

变量作用域

  • 全局变量、局部变量和类型成员变量

  • 全局变量:在一个源代码文件中,在函数和类定义之外声明的变量

  • 全局变量的作用域为其定义的模块,从定义的位置起,直到文件结束位置

  • 通过import语句导入模块,也可以通过全限定名称“模块名.变量名”访问。或者通过from…import语句导入模块中的变量并访问

  • 【例1】全局变量定义示例(global_variable.py)

TAX1 = 0.17   #税率常量17%TAX2 = 0.2    #税率常量20%TAX3 = 0.05   #税率常量5%PI = 3.14      #圆周率3.14
  • 【例2】全局变量、局部变量

num = 100      #全局变量def f():     num = 105    #局部变量     print(num)    #输出局部变量的值#测试代码f();print(num)

 

全局语句global

        在函数体中,可以引用全局变量,但如果函数内部的变量名是第一次出现且在赋值语句之前(变量赋值),则解释为定义局部变量
【例1】函数体错误引用全局变量的示例​​​​​​​

m = 100n = 200def f():       print(m+5)  #引用全局变量m       n += 10 #错误,n在赋值语句前面,解释为局部变量(不存在)#测试代码f()

非局部语句nonlocal

       在函数体中,可以定义嵌套函数,在嵌套函数中,如果要为定义在上级函数体的局部变量赋值,可以使用nonlocal语句,表明变量不是所在块的局部变量,而是在上级函数体中定义的局部变量。nonlocal语句可以指定多个非局部变量。例如nonlocal x, y, z
【例1】非局部语句nonlocal示例​​​​​​​

def outer_func():       tax_rate = 0.17          #上级函数体中的局部变量       print('outer func tax rate =', tax_rate) #输出上级函数体中局部变量的值   def innner_func():       nonlocal tax_rate    #不是所在块的局部变量,而是在上级函数体中定义的局部变量               tax_rate = 0.05  #上级函数体中的局部变量重新赋值               print('inner func tax rate =', tax_rate) #输出上级函数体中局部变量的值    innner_func()                       #调用函数   print('outer func tax rate =', tax_rate)   #输出上级函数体中局部变量的值(已更改)\

 

递归函数

自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身
【例1】使用递归函数实现阶乘​​​​​​​

def factorial(n):    if n == 1: return 1    return n * factorial(n - 1)#测试代码for i in range(1,10): #输出1~9的阶乘        print(i,'! =', factorial(i))

 

递归函数的原理

  • 每个递归函数必须包括如下两个主要部分。

  • (1)终止条件。表示递归的结束条件,用于返回函数值,不再递归调用。例如,factorial()函数的结束条件为“n等于1”。

  • (2)递归步骤。递归步骤把第n步的参数值的函数与第n-1步的参数值的函数关联。例如,对于factorial(),其递归步骤为“n * factorial(n-1)”

  • 例如,调和数的计算公式为:Hn = 1 + 1/2 + . . . + 1/n  故可以使用递归函数实现:

  • (1)终止条件:Hn = 1          #当n==1时

  • (2)递归步骤:Hn = Hn-1 + 1/n   #当n>1时每次递归,n严格递减,故逐渐收敛于1。

思考

Q:使用递归函数计算最大公约数(gcd.py)
R:参考答案​​​​​​​

number1=int(input("请输入一个数:"))number2=int(input("请输入另一个数:"))def gcd(p, q):  #使用递归函数计算p和q的最大公约数    if q == 0: return p    #如果q=0,返回p    return gcd(q, p % q)  #否则,递归调用gcd(q, p % q)#测试代码print(gcd(number1, number2))     #计算并输出p和q的最大公约数

课后练习

1.以下内容关于函数描述正确的是?
A、函数用于创建对象
B、函数可以让重新执行的更快
C、函数是一段代码用于执行特定的任务
D、以上说法都是正确的
2. x = True
def printLine(text):
    print(text, ' Runoob')
printLine('Python')
以上代码输出结果为?
A、Python
B、Python Runoob
C、text Runoob
D、Runoob
3. 如果函数没有使用 return 语句,则函数返回的是?
A、0
B、None 对象
C、任意的整数
D、错误! 函数必须要有返回值。
4.def greetPerson(*name):
    print('Hello', name)

greetPerson('Runoob', 'Google')
以上代码输出结果为?
A、Hello Runoob   Hello Google
B、Hello ('Runoob', 'Google')
C、Hello Runoob
D、错误!函数只能接收一个参数。
5. 关于递归函数描述正确的是?
A、递归函数可以调用程序的使用函数。
B、递归函数用于调用函数的本身。
C、递归函数除了函数本身,可以调用程序的其他所有函数。
D、Python 中没有递归函数。
6. result = lambda x: x * x
print(result(5))
以上代码输出结果为?
A、lambda x: xx
B、10
C、25
D、5
5
7. def Foo(x):
    if (x==1):
        return 1
    else:
        return x+Foo(x-1)
print(Foo(4))
以上代码输出结果为?
A、10
B、24
C、7
D、1
8. 如果我们需要从 math 模块中输出 pi 常量,以下代码正确的是?
A、print(math.pi)
B、print(pi)
C、from math import pi   print(pi)
D、from math import pi   print(math.pi)
9. 以下哪个符号用于从包中导入模块?
A、.
B、*
C、->
D、,
10. numbers = [1, 3, 6]
newNumbers = tuple(map(lambda x: x , numbers))
print(newNumbers)
以上代码输出结果为?
A、[1, 3, 6]
B、(1, 3, 6)
C、[2, 6, 12]
D、(2, 6, 12)

需要了解更多可关注以下公众号,每日更新一篇测试文章

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zemuerqi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值