一、函数的定义与调用
定义:
执行特定任务和完成特定功能的一段代码
作用:
-
复用代码
-
隐藏实现细节
-
提高可维护性
-
提高可读性便于调试
创建:
def 函数名([输入参数]):
"""
函数名 #函数的解释内容
"""
函数体
[return 返回值列表]
调用:
函数名([输入参数])
def su(a,b):
'''
返回a+b的值
'''
c=a+b
return c
re=su(10,20)
print(re)
二、函数的参数
定义函数时()里的参数叫形参(形式参数),它只是一个变量名,供函数体中的代码调用。
函数调用时,传入()里的参数叫实参(实际参数),它是实际的数据,会传递给形参,供函数体执行。
2.1位置参数
根据形参对应的位置进行实参传递
def calc(a,b): #a,b称为形式参数,简称形参,形参的位置是在函数的定义处
c=a+b
return c
re=calc(10,20) #10,20称为实际参数的值,简称实参,实参的位置是函数的调用处
print(re)
位置传参时,形参名称和实参名称可以不一致
def fun(arg1,arg2):
print('arg1',arg1)
print('arg2',arg2)
arg1=100
arg2.append(10)
print('arg1', arg1)
print('arg2', arg2)
n1=11
n2=[22,33,44]
print(n1)
print(n2)
print('调用后'.center(10,'*'))
fun(n1,n2) #位置传参,arg1,arg2是函数定义处的形参,n1,n2是函数调用处的实参,实参名称与形参名称可以不一致
print(n1)
print(n2)
#在函数调用过程中,进行参数的传递:
#如果是不可变对象,在函数体的修改不会影响实参的值 arg1的修改,为100,不会影响n1的值
#如果是可变对象,在函数体的修改会影响到实参的值 arg2的修改,append(10),会影响n2的值
2.2关键字参数
根据形参名称进行实参传递
def su(a,b): #a,b称为形式参数,简称形参,形参的位置是在函数的定义处
c=a+b
return c
re1=su(b=20,a=10) # =左侧的变量名称称为关键字参数
print(re1)
可位置和关键字共同传参
def su(a,b,c): #a,b称为形式参数,简称形参,形参的位置是在函数的定义处
d=a+b+c
return d
re1=su(20,c=10,b=12) # =左侧的变量名称称为关键字参数
print(re1)
#位置和关键字共同传参时,位置参数需在关键字参数前,否则会报错
def su(a,b,c):
d=a+b+c
return d
re1=su(b=20,c=10,12) #报错
print(re1)
2.3默认值参数
函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参
def fun(a,b=10):
print(a,b)
fun(110) #只传一个参数,b采用默认值
fun(20,30) #30替换b默认值10
2.4个数可变的位置参数
定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数
使用*定义个数可变的位置形参
结果为一个元组
def fun(*args):
print(args,type(args))
fun(10) #(10,) <class 'tuple'>
fun(10,20,34) #(10,) <class 'tuple'>
个数可变的位置参数,只能是1个
def ha(*a,*b):
pass #函数报错
2.5个数可变的关键字形参
定义函数时,可能无法事先确定传递的关键字实参的个数时,使用可变的关键字形参
使用**定义个数可变的关键字形参
结果为一个字典
def fun(**kwargs):
print(kwargs,type(kwargs))
fun(a=10) #{'a': 10} <class 'dict'>
fun(a=10,r=90,d=23) #{'a': 10, 'r': 90, 'd': 23} <class 'dict'>
个数可变的关键字参数,只能是1个
def ha(**a,**b):
pass #函数报错
2.6可变位置参数和可变关键字参数
在一个函数的定义过程中,既有个数可变的关键字形参,也有个数可变的位置形参,要求个数可变的位置形参,放在个数可变的关键字形参之前
def tes(*a,**b):
pass
2.7函数的参数总结
fun(10,23,32) #位置传参
l=[12,34,4]
fun(*l) #调用函数时,将列表中的每个元素都转换为位置实参传入
fun(a=10,c=23,b=1) #关键字传参
dic={'a':10,'c':23,'b':1}
fun(dic) #调用函数时,将字典中的键值对转换为关键字实参传入
三、函数的解包
3.1*解包
传递实参时,可以通过*
对迭代对象进行解包
def fun(a,b,*arg):
print(a,b,arg)
ls = [1,2,3,4,5,6]
fun(*ls) #fun(1,2,3,4,5,6) 1 2 (3, 4, 5, 6)
3.2**解包
在传递实参时,可以通过**
对字典对象进行解包。
def fun(a,b, **kwargs):
print(a,b,kwargs)
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
fun(**d) #fun(a=1,b=2,c=3,d=4) 1 2 {'c': 3, 'd': 4}
四、函数的返回值
如果函数没有返回值【函数执行完毕之后,不需要给调用处提供数据】,return可省略不写
def ha():
print('haha')
ha()
函数的返回值,如果是1个,直接返回类型
def te():
return 'test'
print(te())
函数返回多个值时,结果为元组
def fun(num):
odd=[]
even=[]
for i in num:
if i%2:
odd.append(i)
else:
even.append(i)
return odd,even
s=fun([10,23,34,54,45])
print(s) #([23, 45], [10, 34, 54])
print('奇数:',s[0],'偶数',s[1]) #奇数: [23, 45] 偶数 [10, 34, 54]
def he():
return 'hello','world'
print(he()) #('hello', 'world')
函数在定义时,是否需要返回值,视情况而定
五、变量作用域
根据变量的有效范围可分为:
局部变量:
在函数内定义并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量就会成为全局变量
全局变量:
函数体外定义的变量,可作用于函数内外
def fun(a,b):
c=a+b #c为局部变量,因为c是在函数体内进行定义的变量,a,b为函数的形参,作用范围也是内部函数,相当于局部变量
print(c)
name='haha' #name为全局变量
print(name)
def fun2():
print(name)
#调用函数
fun2()
def fun3():
global age #函数内部定义的变量,局部变量,局部变量使用global声明,这个变量实际上就变成了全局变量
age=20
print(age)
fun3()
print(age)
六、lambda函数
语法格式:
lambda arg1,arg2,... : expression
lambda函数一般不会直接定义,通常是作为参数传递给其他函数作为参数使用
f=lambda a,b :a+b
res=f(1,2)
print(res) #3
七、递归函数
7.1定义:
如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数
7.2组成部分:
递归调用与递归终止条件
7.3调用过程:
每递归调用一次函数,都会在栈内存分配一个栈帧
每执行一次函数,都会释放相应的空间
7.4优缺点:
缺点:占用内存多,效率低下
优点:思路和代码简单
def fac(n):
if n==1:
return 1
else:
return n*fac(n-1)
print(fac(6))