Python基础课--第十一节 函数3

    技术2024-10-18  6

    1 高阶函数

    例子 将 lst = [1,2,3,4,5,6,7,8,9,10] 中所有的偶数,保存到一个新的列表中返回

    lst = [1,2,3,4,5,6,7,8,9,10] # 定义一个函数 用来将指定列表中所有的偶数,保存到一个新的列表中返回 def fn(lst): # 参数 要进行筛选列表 # 创建一个新的列表 new_lst = [] for n in lst: # 判断n的奇偶 if n % 2 == 0: new_lst.append(n) return new_lst print(fn(lst)) 结果 [2, 4, 6, 8, 10]

    引出高阶函数

    满足2个条件任意一个都是高阶函数:

    接收一个或多个函数作为参数 将函数作为返回值返回

    例子:将 lst = [1,2,3,4,5,6,7,8,9,10] 中所有的奇数,保存到一个新的列表中返回

    lst = [1,2,3,4,5,6,7,8,9,10] # 定义一个函数 用来将指定列表中所有的偶数,保存到一个新的列表中返回 def fn(lst): # 参数lst 要进行筛选列表 # 定义一个函数 用来测偶数 def fn2(i): if i % 2 == 0: return True # 创建一个新的列表 new_lst = [] for n in lst: # 添加 if not fn2(n): new_lst.append(n) return new_lst print(fn(lst)) 结果 [1, 3, 5, 7, 9]

    例子:将 lst = [1,2,3,4,5,6,7,8,9,10] 中大于5的数,保存到一个新的列表中返回

    lst = [1,2,3,4,5,6,7,8,9,10] # 定义一个函数 用来将指定列表中所有的偶数,保存到一个新的列表中返回 def fn(lst): # 参数lst 要进行筛选列表 # 定义一个函数 用来检测是否大于5 def fn3(i): if i > 5: return True return False # 创建一个新的列表 new_lst = [] for n in lst: # 添加 if fn3(n): new_lst.append(n) return new_lst print(fn(lst)) 结果 [6, 7, 8, 9, 10] 但是上面两个例子,写死了。下面的可以调用不同的函数当我们使用一个函数作为参数时,实际上我们就是将指定的代码传递给了目标函数 lst = [1,2,3,4,5,6,7,8,9,10] # 定义一个函数 用来测偶数 def fn2(i): if i % 2 == 0: return True # 定义一个函数 用来检测是否大于5 def fn3(i): if i > 5: return True return False # 定义一个函数 用来检测是否3的倍数 def fn4(i): if i % 3 == 0: return True return False def fn(func,lst): # 参数lst 要进行筛选列表 # 创建一个新的列表 new_lst = [] for n in lst: # 添加 if func(n): new_lst.append(n) return new_lst print(fn(fn4,lst)) 调用fn4结果 [3, 6, 9]

    2 闭包

    # 将函数作为返回值返回,我们也称为闭包 def fn(): # 在函数内部定义一个函数 def fn2(): print('我是fn2') # 将内部函数作为返回值返回 return fn2 # 返回的是函数对象 print(fn()) 结果 <function fn.<locals>.fn2 at 0x000001717CAD5620> # 将函数作为返回值返回,我们也称为闭包 def fn(): # 在函数内部定义一个函数 def fn2(): print('我是fn2') # 将内部函数作为返回值返回 return fn2 # 返回的是函数对象 # r是一个函数,是调用fn()后返回的函数,这个函数是在fn内部定义,并不是全局函数 r = fn() r() # 调用后值是空 print(r()) 结果 我是fn2 我是fn2 None

    通过闭包可以换创建一些只有当前函数才能访问的对象,还可以将一些私有的数据藏到闭包中

    # 将函数作为返回值返回,我们也称为闭包 def fn(): a = 10 # 在函数内部定义一个函数 def fn2(): print('我是fn2',a) # 将内部函数作为返回值返回 return fn2 # 返回的是函数对象 # r是一个函数,是调用fn()后返回的函数,这个函数是在fn内部定义,并不是全局函数 r = fn() # 值是空 不是全局函数 r() print(a) 结果 我是fn2 10 NameError: name 'a' is not defined # # 求多个数的平均值 # nums = [50,20,60,10,80] # # # sum() 用来求一个列表中元素之和 # print(sum(nums)/len(nums)) nums = [] # 是全局变量 # 定义一个函数,实现就算平均值 def average(n): # 将n添加到列表当中 nums.append(n) # 求平均值 return sum(nums)/len(nums) print(average(10)) print(average(5)) 结果 10.0 7.5

    采用闭包的方式

    def make_average(): nums = [] # 是局部变量 只能内部看到 # 定义一个函数,实现就算平均值 def average(n): # 将n添加到列表当中 nums.append(n) # 求平均值 return sum(nums)/len(nums) return average print(make_average()) a = make_average() print(a(10)) print(a(5)) 结果 <function make_average.<locals>.average at 0x000001AA3E100E18> 10.0 7.5

    形成闭包的条件:

    函数嵌套 将内部函数作为返回值返回 内部函数必须使用到外部函数的变量

    当不希望别人去修改的时候,使用闭包

    3 装饰器的引入

    # 求任意两个数的和 def add(a,b): print('开始计算') print('计算结束') return a + b # 求任意两个数的乘积 def mul(a,b): return a * b r = add(1,20) print(r) 结果 开始计算 计算结束 21

    我们可以通过修改函数中的代码来完成装饰,但是会产生一些问题:

    修改的函数很多 不方便后期的维护 会违反开闭原则(ocp) 程序设计 要求对程序的扩展,但是要关闭对程序的修改

    不修改原函数,来对函数进行扩展

    # 不修改原函数,来对函数进行扩展 def fn(): print('我是fn函数') # 定义一个函数 对fn进行扩展 def fn2(): print('函数开始执行') fn() print('函数执行结束') fn2() 结果 函数开始执行 我是fn函数 函数执行结束 # 求任意两个数的和 def add(a,b): return a + b # 求任意两个数的乘积 def mul(a,b): return a * b r = add(1,20) def new_add(a,b): print('函数开始执行') r = add(a,b) print('函数执行结束') return r result = new_add(1,2) print(result) 结果 函数开始执行 函数执行结束 3 上述较为麻烦因此需要通用的方式了对函数进行扩展

    4 装饰器的使用

    def fn(): print('我是fn函数') def add(a,b): return a + b def start_end(old): # 类似于start_end(old)就是装饰器 # 用来对其他的函数进行扩展 扩展函数执行的时候打印 开始执行 执行后打印 执行结束 # 参数old---要扩展的函数对象 # 创建一个函数 def new_function(*args,**kwargs): # 参数装包 转换为一个个元组或者字典 # *args用来接收所有的位置参数,,**kwargs用来接收所有的关键字参数 print('开始执行') # 要调用被扩展的函数 result = old(*args,**kwargs) # 把位置参数拆包,放到元组进去,,或者把关键字 转换字典 传进去 print('执行结束') return result # 返回新函数 return new_function f = start_end(add) r = f(111,222) print(r) 结果 开始执行 执行结束 333 start_end(old) 类似于这样的函数其实就是一个装饰器,通过装饰器可以在不修改原函数的情况下对函数进行扩展,在开发当中,都是通过装饰器来扩展函数的功能@

    在Python的函数中偶尔会看到函数定义的上一行有@functionName的修饰,当解释器读到@的这样的修饰符之后,会先解析@后的内容,直接就把@下一行的函数或者类作为@后边的函数的参数,然后将返回值赋值给下一行修饰的函数对象。 比如: @a @b def c(): … python会按照自下而上的顺序把各自的函数结果作为下一个函数(上面的函数)的输入,也就是a(b(c())) ———————————————— 版权声明:本文为博主「saberpan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/saberpan/article/details/85258781

    ‘@’引用已有的函数,对下面的函数进行修饰。引用函数必须放在修饰函数的上面,引用函数的返回值,返回给被修饰的函数 https://www.cnblogs.com/liangxiyang/p/11200476.html

    例子

    def fn(): print('我是fn函数') def add(a,b): return a + b def start_end(old): # 类似于start_end(old)就是装饰器 # 用来对其他的函数进行扩展 扩展函数执行的时候打印 开始执行 执行后打印 执行结束 # 参数old---要扩展的函数对象 # 创建一个函数 def new_function(*args,**kwargs): # 参数装包 转换为一个个元组或者字典 # *args用来接收所有的位置参数,,**kwargs用来接收所有的关键字参数 print('开始执行') # 要调用被扩展的函数 result = old(*args,**kwargs) # 把位置参数拆包,放到元组进去,,或者把关键字 转换字典 传进去 print('执行结束') return result # 返回新函数 return new_function f = start_end(add) @start_end def speak(): print('大家加油') speak() 结果 开始执行 大家加油 执行结束
    Processed: 0.036, SQL: 9