1、函数的创建与调用
函数名要遵守标识符的规则
def calc(a,b): #a,b称为形式参数,简称形参,形参的位置是在函数的定义处
c = a+b
return c
result = calc(10,20) #10,20称为实际参数的值,简称实参,实参的位置是函数的调用处
print(result)
输出结果:
30
2、参数传递
2.1
#位置实参
#对应的位置互相传(一个萝卜一个坑),如上面的实参第一个位置的10传给形参第一个位置的a
#关键字实参
res = calc(b=10,a=20) #使用了关键字参数,就会到定义处找到关键字名字相同的去赋值
print(res)
输出结果:
30
2.2 函数参数传递的内存分析
def fun(arg1,arg2):
print("arg1",arg1)
print("arg2",arg2)
arg1 = 100
arg2.append(10)
print("arg1", arg1)
print("arg2", arg2)
n1 = 11
n2 = [20,30,40]
print('n1',n1)
print('n2',n2)
fun(n1,n2)
print('n1',n1)
print('n2',n2)
#在函数调用过程中,进行参数的传递
#如果是不可变对象,在函数体的修改不会影响实参的值 arg1修改为100,不会影响n1的值 (整数是不可变对象)
#如果是可变对象,在函数体的修改会影响到实参的值 arg2的修改 append(10),会影响到n2的值 (列表是可变对象)
输出结果:
n1 11
n2 [20, 30, 40]
arg1 11
arg2 [20, 30, 40]
arg1 100
arg2 [20, 30, 40, 10]
n1 11
n2 [20, 30, 40, 10]
#在函数调用过程中,进行参数的传递
#如果是不可变对象,在函数体的修改不会影响实参的值 arg1修改为100,不会影响n1的值 (整数是不可变对象)
#如果是可变对象,在函数体的修改会影响到实参的值 arg2的修改 append(10),会影响到n2的值 (列表是可变对象)
3、函数的返回值
如果函数的返回值有多个,返回的结果为元组
#如果函数的返回值有多个,返回的结果为元组
def fun1():
return 'hello','world'
print(fun1()) #输出('hello', 'world') 为元组类型
输出结果:
(‘hello’, ‘world’)
4、函数参数定义_默认值参数
#函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参
def fun(a,b=10): #b称为默认值参数
print(a,b)
fun(100)
fun(20,30)
输出结果:
100 10
20 30
print('hello')
print('world') #print的其中一个默认值end其实是换行\n,我们修改一下
print('hello',end='\t')
print('world')
输出结果:
hello
world
hello world
5、
当不知道要传递几个参数时,可以在形参处写 args,输出的结果是一个元组
函数定义时的 个数可变的位置参数————加1个
#当不知道要传递几个参数时
#可以在形参处写 *args 结果是一个元组
def fun(*args): #函数定义时的 个数可变的位置参数
print(args) #输出时是一个元组
fun(10)
fun(10,20)
fun(10,20,30)
输出结果:
(10,)
(10, 20)
(10, 20, 30)
个数可变的关键字形参————加2个*,输出结果是一个字典
def fun1(**args): #个数可变的关键字形参————加2个*
print(args) #输出时是一个字典
fun1(a=10)
fun1(a=10,b=20)
fun1(a=10,b=20,c=30)
输出结果:
{‘a’: 10}
{‘a’: 10, ‘b’: 20}
{‘a’: 10, ‘b’: 20, ‘c’: 30}
# def fun3(*args,*a):
# pass #以上程序会报错,因为只能定义一个个数可变的位置参数
# def fun3(**args,**a):
# pass #以上程序也会报错,因为也只能定义一个个数可变的关键字参数
在一个函数的定义过程中,既有个数可变的位置参数,也有个数可变的关键字参数,要求,个数可变的位置参数要在个数可变的关键数参数之前
def fun4(*args1,**args2):
print(args1,args2) #不会报错
fun4(10,20,a=55)
#fun4(m=6,a=55,56,20) #会报错
#fun4(6,a=55,56,20) #会报错
输出结果:
(10, 20) {‘a’: 55}
# def fun5(**args1,*args2):
# pass #会报错
#在一个函数的定义过程中,既有个数可变的位置参数,也有个数可变的关键字参数,要求,个数可变的位置参数要在个数可变的关键数参数之前
6、函数的调用
def fun(a,b,c):
print("a=",a)
print("b=",b)
print("c=",c)
#函数的调用
fun(10,20,30) #位置传参(对应位置传递参数)
lst = [11,22,33]
#fun(lst) #会报错
fun(*lst) #在函数调用时,将列表中的每一个元素都转换为位置实参传入
fun(a=100,b=200,c=300) #关键字参数传入
dict = {'a':54,'b':45,'c':18}
fun(**dict) #注意,实参是字典时,前面加两颗*
输出结果:
a= 10
b= 20
c= 30
a= 11
b= 22
c= 33
a= 100
b= 200
c= 300
a= 54
b= 45
c= 18
7、函数定义时的形参的顺序问题
在*之后的参数只能采用关键字参数传递
def fun5(a,b,*,c,d): #在*之后的参数只能采用关键字参数传递
print('a=',a)
print('b=',b)
print('c=',c)
print('d=',d)
#fun(10,20,30,40) #会报错
fun5(a=10,b=20,c=30,d=40)
fun5(11,12,c=13,d=14)
输出结果:
a= 10
b= 20
c= 30
d= 40
a= 11
b= 12
c= 13
d= 14
以下形参的顺序都是允许的
def fun6(a,b,*,c,d,**args):
pass
def fun7(*args1,**args2):
pass
def fun8(a,b=10,*args1,**args2):
pass
#以上三种形参的顺序都是允许的
8、
def fun():
global age
age = 24
print(age)
fun()
print(age)
#函数内部定义的变量,局部变量,局部变量使用global声明,这个变量实际上就变成了全局变量
输出结果:
24
24
9、递归函数
(1)在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数
(2)递归的组成部分:递归调用与递归终止条件 (所以语法结果是if…else…) 一般if后面跟终止条件
(3)递归的调用过程:每递归调用一次函数,都会在栈内存分配一个栈帧;每执行完一次函数,都会释放相应的空间
(4)递归缺点:占用内存多,效率低下;优点:思路和代码简单
使用递归计算阶层
#使用递归计算阶层
def fac(a):
if a==1: #出口
return 1
else:
res = a*fac(a-1)
return res
print(fac(6))
输出结果:
720
使用递归计算斐波那契数列 1 1 2 3 5 8…(第三项是前两项数字之和)
def fib(n):
if n==1 or n==2:
return 1
else:
res = fib(n-1)+fib(n-2)
return res
#输出斐波那数列第6位上的数字
print(fib(6))
#输出这个数列的前6位的数字
for i in range(1,7):
print(fib(i))
输出结果:
8
1
1
2
3
5
8