27.函数
- 函数的定义
def 函数名 ([输入参数]):
函数体
[return xxx]
- 函数的调用
- 语法如下:
函数名([实际参数])
- 一个函数的使用示例:
def calc(a,b):
c = a + b
return c
result = calc(100,200)
print(result) #300
- 函数的返回值
- 函数返回多个值时,返回的结果为元组
- 函数返回值是一个,直接返回该值
- 如果函数没有返回值,return可以省略不写
#函数的返回值为多个
def cla(num):
odd = []
even = []
for i in num:
if i % 2:
odd.append(i)
else:
even.append(i)
return odd,even
lst = [12,56,24,11,33,59,88]
print(cla(lst)) #([11, 33, 59], [12, 56, 24, 88])
- 函数的参数定义
- 函数定义默认参数:函数定义时,给形参设置默认值,当函数的使用者不提供默认形参对应的实参值,则使用默认形参的值。默认参数需要放在非默认参数后面。
#定义函数时,给形参设置默认值
def func(a,b = 100):
return a + b
print(func(100)) #200
print(func(100,200))#300
- 个数可变的位置形参(只能一个):定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数。使用*定义个数可变的位置形参,结果为一个元组
def func(*args):
print(args) #结果为一个元组,(100, 200, 300)
func(100,200,300)
- 个数可变的关键字形参(只能一个):定义函数时无法事先确定传递的关键字实参的个数时,使用可变的关键字形参。使用**定义个数可变的关键字形参,结果为一个字典
def func(**kwargs):
print(args) #结果为一个字典,{'a': 100, 'b': 200, 'c': 300}
func(a = 100,b = 200,c = 300)
- 示例如下:
def func(a,b,c):
print(a)
print(b)
print(c)
lst = [10,20,30]
func(*lst) #将列表这个序列的每个元素转化为位置实参传入,又称函数的打散
dic = {'a':100,'b':200,'c':300}
func(**dic) #将字典这个序列中的每个键值对转化为关键字实参传入,又称函数的打散
#函数定义时的形参的顺序问题
def fun(a,b,*,c,d): #有*表示cd只能采用关键字实参传递
print(c) # 3
fun(1,2,c = 3,d = 4)
def func(*args,**kargs):
print(args)
print(kargs)
lst = [12,'hello']
dict = {'name':'张三','age':23}
func(*lst,**dict) #(12, 'hello') {'name': '张三', 'age': 23}
- 注意:在一个函数的定义过程中,既有个数可变的关键字形参,也有个数可变的位置形参,要求个数可变的位置形参放在个数可变的关键字形参之前
def func(* arg, **args):
print(arg) #(100,)
print(args) #{'a': 200, 'b': 300}
func(100, a=200, b = 300);
- 函数的递归
#函数递归实现斐波那契数列
def fac(n):
if n== 1:
return 1
elif n == 2:
return 1
else:
return fac(n - 1) + fac(n - 2)
#输出斐波那契数列第六位的数字
print(fac(6)) #8 1,1,2,3,5,8
28.匿名函数
- 匿名函数:没有名称的函数。在python中使用lambda关键字来定义匿名函数。
- 语法如下:
变量名 = lambda 参数:返回值
- 示例
sum = lambda arg1, arg2 : arg1 + arg2
print(sum(100, 200)) # 300
- 匿名函数和函数一样,也是function类型的对象
func = lambda a, b : a if a > b else b
# <function <lambda> at 0x0000015A7DF9F040> <class 'function'>
print(func, type(func))
29.闭包
- 闭包:就是嵌套在函数1中的函数2,函数2对外部作用域中的变量(函数1中定义的)进行了引用,函数1返回函数2。
- 闭包的作用:
- 可以延续外部函数的非局部变量的生命周期
- 良好的封装性,只有闭包可以访问非局部变量,函数外不可以访问。
- 非局部变量:又称之为自由变量,就是闭包引用的在外部函数定义的变量。对于闭包来说就是非局部变量,拥有非局部变量的函数就是闭包。非局部变量和局部变量是有区别的,如下所示:
def wrapper():
a = 100
def getA():
c = 200
print(a)
return getA
closure = wrapper()
# 函数名.__code__.co_freevars 查看函数的自由变量
print(wrapper.__code__.co_freevars) # ()
# 函数名.__code__.co_varnames 查看函数的局部变量
print(wrapper.__code__.co_varnames) # ('getA',)
print(closure.__code__.co_freevars) # ('a',)
print(closure.__code__.co_varnames) # ('c',)
# 函数名.__closure__ 获取具体的自由变量对象,属性cell_contents 获取自由变量具体的值
print(closure.__closure__[0].cell_contents) # 100
- 闭包的特点:闭包内部不能够修改非局部变量的地址
def wrapper():
list = []
def innerFunc():
list.append(100)
return list
return innerFunc
closure = wrapper()
closure()
closure()
closure()
closure()
# [100, 100, 100, 100, 100]
print(closure())
- 示例:
def wrapper():
a = 100
def getA():
c = 200
print(a)
return getA
closure = wrapper()
# <function wrapper.<locals>.getA at 0x000001AB4E16B3A0> <class 'function'>
print(closure, type(closure))