27.函数

  1. 函数的定义
def 函数名 ([输入参数]):
    函数体
    [return xxx]
  1. 函数的调用
    1. 语法如下:
    函数名([实际参数])
    
    1. 一个函数的使用示例:
    def calc(a,b):
        c = a + b
        return c
    
    result = calc(100,200)
    print(result)   #300
    
  2. 函数的返回值
    1. 函数返回多个值时,返回的结果为元组
    2. 函数返回值是一个,直接返回该值
    3. 如果函数没有返回值,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])
    
  3. 函数的参数定义
    1. 函数定义默认参数:函数定义时,给形参设置默认值,当函数的使用者不提供默认形参对应的实参值,则使用默认形参的值。默认参数需要放在非默认参数后面。
    #定义函数时,给形参设置默认值
    def func(a,b = 100):
        return a + b
    
    print(func(100))    #200
    print(func(100,200))#300
    
    1. 个数可变的位置形参(只能一个):定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数。使用*定义个数可变的位置形参,结果为一个元组
    def func(*args):
        print(args) #结果为一个元组,(100, 200, 300)
    
    func(100,200,300)
    
    1. 个数可变的关键字形参(只能一个):定义函数时无法事先确定传递的关键字实参的个数时,使用可变的关键字形参。使用**定义个数可变的关键字形参,结果为一个字典
    def func(**kwargs):
        print(args) #结果为一个字典,{'a': 100, 'b': 200, 'c': 300}
    
    func(a = 100,b = 200,c = 300)
    
    1. 示例如下:
    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}
    
    1. 注意:在一个函数的定义过程中,既有个数可变的关键字形参,也有个数可变的位置形参,要求个数可变的位置形参放在个数可变的关键字形参之前
    def func(* arg, **args):
        print(arg)  #(100,)
        print(args) #{'a': 200, 'b': 300}
    func(100, a=200, b = 300);
    
  4. 函数的递归
#函数递归实现斐波那契数列
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.匿名函数

  1. 匿名函数:没有名称的函数。在python中使用lambda关键字来定义匿名函数。
    1. 语法如下:
    变量名 = lambda 参数:返回值
    
    1. 示例
    sum = lambda arg1, arg2 : arg1 + arg2
    print(sum(100, 200)) # 300
    
    
  2. 匿名函数和函数一样,也是function类型的对象
func = lambda a, b : a if a > b else b
# <function <lambda> at 0x0000015A7DF9F040> <class 'function'>
print(func, type(func))

29.闭包

  1. 闭包:就是嵌套在函数1中的函数2,函数2对外部作用域中的变量(函数1中定义的)进行了引用,函数1返回函数2。
  2. 闭包的作用:
    1. 可以延续外部函数的非局部变量的生命周期
    2. 良好的封装性,只有闭包可以访问非局部变量,函数外不可以访问。
  3. 非局部变量:又称之为自由变量,就是闭包引用的在外部函数定义的变量。对于闭包来说就是非局部变量,拥有非局部变量的函数就是闭包。非局部变量和局部变量是有区别的,如下所示:
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

  1. 闭包的特点:闭包内部不能够修改非局部变量的地址
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())
  1. 示例:
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))