二、什么是高阶函数
- 在Python中,函数是一等对象
- 一等对象一般都会具有如下特点:
① 对象是在运行时创建的
② 能赋值给变量或作为数据结构中的元素
③ 能作为参数传递
④ 能作为返回值返回
就是将一个一个的功能通过函数来完成,python支持函数式编程,但python不是函数式编程语言。
接收函数作为参数,或者将函数作为返回值的函数是高阶函数
当我们使用一个函数作为参数时,实际上是将指定的代码传递进了目标函数。
- 高阶函数至少要符合以下两个特点中的一个
① 接收一个或多个函数作为参数
② 将函数作为返回值返回
为什么需要高阶函数呢?
例子:定义一个函数,可以将指定列表中的所有的偶数,或所有奇数,或大于5的数等,保存到一个新的列表中返回
用普通的函数实现
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def fn(lst): # 创建一个新列表 new_list = [] # 对列表进行筛选 for n in lst: # # 判断n的奇偶 # if n % 2 == 0: # new_list.append(n) # # 取奇数 # if n % 2 != 0: # new_list.append(n) # # 取大于5的数 # if n > 5: # new_list.append(n) if not fn2(n): new_list.append(n) # 返回新列表 return new_list print(fn(l))
或:
def fn(lst): def fn2(i): if i % 2 == 0: return True return False def fn3(i): if i > 5: return True return False # 创建一个新列表 new_list = [] # 对列表进行筛选 for n in lst: # # 判断n的奇偶 if fn2(n): new_list.append(n) # 大于5的数 if fn3(n): new_list.append(n) # 返回新列表 return new_list print(fn(l))
使用高阶函数实现:
# 在函数内部在定义一个函数,用来检查一个任意数字是否是偶数 def fn2(i): if i % 2 == 0: return True return False def fn3(i): if i > 5: return True return False def fn(func, lst): # 创建一个新列表 new_list = [] # 对列表进行筛选 for n in lst: if func(n): new_list.append(n) # 返回新列表 return new_list # 当传fn2函数作为参数时,实际上是将fn2的代码传递 print(fn(fn2, l)) # [2, 4, 6, 8, 10] print(fn(fn3, l)) # [6, 7, 8, 9, 10]三、filter()函数
filter()可以从序列中过滤出符合条件的元素,保存到一个新的序列中。
参数:
1.函数,根据该函数来过滤序列(可迭代的结构)
2.需要过滤的序列(可迭代的结构)
返回值:
过滤后的新序列(可迭代的结构)
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 在函数内部在定义一个函数,用来检查一个任意数字是否是偶数 def fn2(i): if i % 2 == 0: return True return False r = filter(fn2, l) print(list(r)) #[2, 4, 6, 8, 10]
fn2是作为参数传递进filter()函数中
而fn2实际上只有一个作用,就是作为filter()的参数
filter()调用完毕以后,fn2就已经没用了。
匿名函数 lambda 函数表达式 (语法糖)
lambda函数表达式专门用来创建一些简单的函数,他是函数创建的又一种方式
语法:lambda 参数列表 : 返回值
匿名函数一般都是作为参数使用,其他地方一般不会使用.
def fn5(a, b): return a + b print(fn5(123, 456)) # 579 # 用lambda来代替这个函数 lambda a, b: a + b print((lambda a, b: a + b)(123,456)) # 579 # 将lambda表达式,赋值给一个变量 result = lambda a, b: a + b print(result(123,456)) #
def fn4(i): if i % 3 == 0: return True return False # 第一次改造 def fn4(i): return i % 3 == 0 # 改造lambda lambda i: i % 3 == 0 # r = filter(fn4(), l) r = filter(lambda i: i % 3 == 0, l) print(list(r))五、map函数
map()函数可以对可跌倒对象中的所有元素做指定的 *** 作,然后将其添加到一个新的对象中返回
l = [1,2,3,4,5,6,7,8,9,10] r = map(lambda i : i+1 , l) print(r) #六、sort函数
该方法用来对列表中的元素进行排序
sort()方法默认是直接比较列表中的元素的大小
在sort()可以接收一个关键字参数 , key
key需要一个函数作为参数,当设置了函数作为参数
每次都会以列表中的一个元素作为参数来调用函数,并且使用函数的返回值来比较元素的大小
l = ['bb','aaaa','c','ddddddddd','fff'] l.sort() print(l) # ['aaaa', 'bb', 'c', 'ddddddddd', 'fff'] l = ['bb','aaaa','c','ddddddddd','fff'] l.sort(key=len) print(l) # ['aaaa', 'bb', 'c', 'ddddddddd', 'fff'] # ['c', 'bb', 'fff', 'aaaa', 'ddddddddd'] l = [2,5,'1',3,'6','4'] l.sort(key=int) print(l) # ['1', 2, 3, '4', 5, '6']七、sorted()
这个函数和sort()的用法基本一致,但是sorted()可以对任意的序列进行排序
并且使用sorted()排序不会影响原来的对象,而是返回一个新对象
l = [2, 5, '1', 3, '6', '4'] print('排序前:', l) print(sorted(l, key=int)) print('排序后:', l) 控制台打印; 排序前: [2, 5, '1', 3, '6', '4'] ['1', 2, 3, '4', 5, '6'] 排序后: [2, 5, '1', 3, '6', '4']八、闭包
将函数作为返回值返回,也是一种高阶函数
这种高阶函数我们也称为叫做闭包,通过闭包可以创建一些只有当前函数能访问的变量
可以将一些私有的数据藏到的闭包中
形成闭包的条件:
① 函数嵌套
② 将内部函数作为返回值返回
③ 内部函数必须要使用到外部函数的变量
# 外部函数 def make_averager(): # 创建一个列表,用来保存数值 nums = [] # 创建内部函数,用来计算平均值 def averager(n) : # 将n添加到列表中 nums.append(n) # 求平均值 return sum(nums)/len(nums) return averager averager = make_averager() print(averager(10)) print(averager(20)) print(averager(30)) print(averager(40))九、装饰器
1、引入装饰器
举例: 希望函数可以在计算前,打印开始计算,计算结束后打印计算完毕
def add(a , b): ''' 求任意两个数的和 ''' print("开始计算...") r = a + b print('计算结束...') return r def mul(a , b): ''' 求任意两个数的积 ''' print("开始计算...") r = a * b print('计算结束...') return r
弊端:如果多个函数需要打印计算开始和计算结束,那么就要给每一个函数都要添加两行语句。
我们希望在不修改原函数的情况下,来对函数进行扩展
def fn(): print('我是fn函数....') # 只需要根据现有的函数,来创建一个新的函数 def fn2(): print('函数开始执行~~~') fn() print('函数执行结束~~~') fn2() 控制台打印: 函数开始执行~~~ 我是fn函数.... 函数执行结束~~~ def new_add(a,b): print('计算开始~~~') r = add(a,b) print('计算结束~~~') return r r = new_add(111,222) print(r) 控制台打印结果: 计算开始~~~ 计算结束~~~ 333
将new_add变成一个通用的函数,不用对每一个需要扩展的函数,都要创建一个新的函数。
上边的方式,已经可以在不修改源代码的情况下对函数进行扩展了
但是,这种方式要求我们每扩展一个函数就要手动创建一个新的函数,实在是太麻烦了
为了解决这个问题,我们创建一个函数,让这个函数可以自动的帮助我们生产函数。
def add(a , b): ''' 求任意两个数的和 ''' r = a + b return r def mul(a , b): ''' 求任意两个数的积 ''' r = a * b return r def begin_end(old): ''' 用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束 参数: old 要扩展的函数对象 ''' # 创建一个新函数 将参数装包成一个元组或者一个字典 def new_function(*args , **kwargs): print('开始执行~~~~') # 调用被扩展的函数 ,将参数拆包成一个元组或一个字典 result = old(*args , **kwargs) print('执行结束~~~~') # 返回函数的执行结果 return result # 返回新函数 return new_function f = begin_end(fn) f2 = begin_end(add) f3 = begin_end(mul) # r = f() # r = f2(123,456) # r = f3(123,456) # print(r)
像begin_end()这种函数我们就称它为装饰器
通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
在开发中,我们都是通过装饰器来扩展函数的功能的。(将旧函数作为参数传递给新的函数,新函数对旧函数进行升级)
在定义函数时,可以通过@装饰器,来使用指定的装饰器,来装饰当前的函数
可以同时为一个函数指定多个装饰器,这样函数将会安装从内向外的顺序被装饰
@begin_end def say_hello(): print('大家好~~~') say_hello() @fn3 @begin_end def say_hello(): print('大家好~~~') say_hello() 先执行begin_end装饰,在执行fn3装饰。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)