函数的创建和调用
什么是函数
函数就是执行特定任务和完成特定功能的一段代码
为什么需要函数
- 复用代码
- 隐藏实现细节
- 提高可维护度
- 提高可读性便于调试
函数的创建
def 函数名(参数):
函数体
return xxx
函数的参数传递
# 函数调用的参数传递
# 位置实参:根据形参对应的位置进行实参传递
def cal(x,y): # x与y称为形式参数
z = 10*x-y
return z
res = cal(1,4) # 6和2称为实际参数,用res接收z的值
print(res)
6
# 关键字实参:根据形参名进行实惨传递
res = cal(y=4,x=1)
print(res)
6
在函数调用过程中,进行参数的传递,如果是不可变对象,在函数体的修改不会影响实参的值;如果是可变对象,在函数体的修改会影响实参的值。
函数的返回值
# 函数返回多个值时,结果为元组
def fun(num):
odd=[] # 用于存奇数
even=[] # 用于存偶数
for i in num:
if i%2:
odd.append(i)
else:
even.append(i)
return odd,even
list=[18,23,45,86,2,4,6,1]
print(fun(list))
([23, 45, 1], [18, 86, 2, 4, 6])
1)如果函数没有返回值,即函数执行完成后,不需要给调用处提供数据,return
可以省略不写;
2)函数的返回值,如果是1个,直接返回原类型;
3)函数的返回值,如果是多个,返回结果为元组
函数的参数定义
默认值参数
# 函数定义默认值参数:函数定义时,给形参设置默认值,只有与默认值不符时才需要传递实惨
def func(a,b=2):
print(a,b)
func(10)
func(10,3)
10 2
10 3
个数可变的参数
# 个数可变的位置参数
# 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数,使用*定义个数可变的位置形参,结果为一个元组
def func(*num): # 个数可变的位置参数,只能定义一个
print(num)
print(num[0])
func(2)
func(3,4)
func(3,4,5)
(2,)
2
(3, 4)
3
(3, 4, 5)
3
# 个数可变的关键字参数
# 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数,使用**定义个数可变的关键字形参,结果为一个字典
def func(**num): # 个数可变的关键字参数,只能定义一个
print(num)
# print(num[0])
func(a=2)
func(a=3,b=4)
func(a=3,b=4,c=5)
{'a': 2}
{'a': 3, 'b': 4}
{'a': 3, 'b': 4, 'c': 5}
def func(*agrs1,**args2): # 个数可变的位置形参和个数可变的关键字形参可以有两个
pass
def func(**args1,*args2): # 个数可变的位置形参必须在个数可变的关键字形参之前
pass
File "<ipython-input-19-b9debc113ca5>", line 1
def func(**args1,*args2):
^
SyntaxError: invalid syntax
def func(a,b,c):
print('a=',a)
print('b=',b)
print('c=',c)
list=[2,3,4]
func(*list) # 加了*后,会将列表中的每个元素转换为位置参数传入
a= 2
b= 3
c= 4
dic={'a':2,'b':5,'c':9}
func(**dic) # 加了**后,会将字典中的每个键值对转换为关键字参数传入
a= 2
b= 5
c= 9
# 位置传参和关键字传参可混合使用。若要求c和d只能采用关键字参数传入,则要在c和d之前价格*
def func(a,b,*,c,d): # *之后的参数在函数调用时,只能采用关键字传参
print('a=',a)
print('b=',b)
print('c=',c)
print('d=',d)
func(10,29,c=9,d=2)
func(10,29,9,2) # c和d必须用关键字传参
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-d8638f3a0c13> in <module>
----> 1 func(10,29,9,2)
TypeError: func() takes 2 positional arguments but 4 were given
变量的作用域
局部变量
在函数内定义并使用的变量,只在函数内部有效。
局部变量用global
声明,就会变成全局变量。
def func(a,b):
s=a*b
return s # a,b,s都是局部变量,外部不可使用
print(s)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-38-767dad8f5bbf> in <module>
3 return s # a,b,s都是局部变量,外部不可使用
4
----> 5 print(s)
NameError: name 's' is not defined
def func(a,b):
global c
c=a*b
return c # a,b,c都是局部变量,外部不可使用
func(1,2)
print(c)
2
全局变量
函数体外定义的变量,可作用于函数内外。
递归函数
什么是递归函数
如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数。
组成部分
递归调用和递归终止条件
调用过程
每递归调用一次函数,都会在栈内存分配一个栈帧;每执行完一次函数,都会释放相应的空间。
优缺点
缺点:占用内存多,效率低下;
优点:思路和代码简单
# 阶乘
def func(n):
if n==1:
return 1
else:
return n*func(n-1)
func(6)
720
# 斐波那契数列:从第三项开始等于前两项的和
def func(n):
if n==1:
return 1
elif n==2:
return 1
else:
return func(n-1)+func(n-2)
func(9)
34
for i in range(1,10):
print(func(i))
1
1
2
3
5
8
13
21
34