Python函数式编程——高阶函数(Higherorder function)
1.函数式编程
函数
是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
而函数式编程
——Functional Programming
,虽然也可以归结到面向过程的程序设计,但其思想更接近抽象的计算。
我们首先要搞明白计算机(Computer
)和计算(Compute
)的概念。 在计算机的层次上,CPU
执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言
是最贴近计算机的语言。
而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件
越远。
对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C
语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Python
语言。
函数式编程就是一种抽象程度很高的编程范式。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
Python
对函数式编程提供了部分支持。由于Python
允许使用变量,因此,Python
不是纯函数式编程语言。
- 变量可以指向函数
例如Python内置求绝对值函数abs()
>>> abs(-5) 5 >>> f = abs >>> f
可以看见,只写abs
只是函数本身,而abs(-5)
才是函数调用,实际我们如果需要函数的结果,可以将函数赋值给变量
例如:
>>> i = abs(-5) >>> i 5 >>> f = abs >>> f >>> f(-5) 5
将调用函数的结果,赋值给变量 i
,这样变量就可以打印出结果,如果将函数本身赋值给变量f
,那么变量也拥有这个函数的功能,这个变量将指向这个函数,使用变量 f ()
来调用函数和直接调用abs()
效果是一样的。
- 函数名也可以是变量
函数是由def
定义,函数名,括号,括号参数,冒号,函数体组成,那么函数名是什么呢,可以发现,函数名是指向函数的变量,例如abs()
这个函数,可以将abs
看成变量,它指向一个可以求绝对值的函数,如果把abs
指向其他的对象,例如我们给abs
赋值,那看看还会指向求绝对值的函数吗
>>> abs = 5 >>> abs(-5) Traceback (most recent call last): File "", line 1, in abs(-5) TypeError: 'int' object is not callable >>> abs 5
TypeError: 'int' object is not callable
提示,类型错误,int
类型是不可以被调用的,我们看到,abs
这个变量被赋值5
,然后使用abs(-5)
调动函数,发现异常,此时abs
变量指向的不是函数,而是一个int
类型的 5
,实际上,我们工作或是开发中写代码,是不能这么写的,由此可以看出函数名其实就是变量。
注意:由于 abs
函数实际上是定义在 import builtins
模块中的,所以要让修改 abs
变量的指向在其它模块也生效可以使用。
import builtins builtins.abs = 10
2.引出高阶函数
上面的例子,函数可以传参数,而函数名可以做变量,那我们函数里面的参数也可以为函数名。
代码中的total
为高阶函数
# -*- coding: utf-8 -*- # @File : 引出高阶函数.py # @author: Flyme awei # @email : Flymeawei@163.com # @Time : 2022/8/21 10:00 def fun(i): return i * 2 def total(x, y, fun): return fun(x) + fun(y) add_sum = total(1, 2, fun) print(add_sum) # 6
下面代码test
称为高阶函数
# -*- coding: utf-8 -*- # @File : 高阶函数.py # @author: Flyme awei # @email : Flymeawei@163.com # @Time : 2022/8/21 10:12 def fac(n): # 定义一个递归函数计算阶乘 if n == 1: # 递归终止条件 return 1 else: # 在test()函数的函数体内调用该本身 return n*fac(n-1) # 递归调用 def test(list_, fun): # 将函数fac本身作为参数传进来,test称为高阶函数 new_list = [] for x in list_: new_list.append(fun(x)) print(new_list) ls = [1, 2, 3, 4, 5, 6, 7] test(ls, fac) # 调用函数test 并把参数lst和fac传入
3.Python内置高阶函数
# -*- coding: utf-8 -*- # @File : 内置高阶函数.py # @author: Flyme awei # @email : Flymeawei@163.com # @Time : 2022/8/21 14:10 from functools import reduce ''' 1.map函数:把一个可迭代对象中的每个元素转换为一个新的对象,最后返回一个新的可迭代对象''' # map(fun, iterables) lst = [1, 2, 3, 4, 5] ite = map(lambda x: x ** 2, lst) print(ite) # for i in ite: print(i, end=' ') # 1 4 9 16 25 ''' 2.reduac() 把一个可迭代对象中的每个元素都做聚合处理,返回一个聚合之后的值 from functools import reduce reduce(function, sequence[, initial]) -> value''' # function:一共有两个参数的函数 # sequence:是一个序列,是一些数据的集合,或者是一组数据,可迭代对象 # initial:可选,初始参数 返回值:返回函数计算的结果 va = reduce(lambda x, y: x + y, lst) # 求累加 print('ns =', va) # s = 15 def max_(x, y): if x > y: return x max1 = reduce(max_, iter((3, 2))) # 求最大值 print(max1) # 3 ''' 3.filter 把一个可迭代对象中的元素做过滤操作,若果func返回值为True是留下,否则过滤掉''' staff = [ {'name': '张三', 'age': 18, 'salary': 2000}, {'name': '李四', 'age': 20, 'salary': 4000}, {'name': '麻子', 'age': 22, 'salary': 6000}] # 过滤留下大于18岁的员工 lst_age = filter(lambda x: x['age'] > 18, staff) print('大于18岁的员工:', list(lst_age)) # 工资大于4000的员工 lst_salary = filter(lambda x: x['salary'] > 4000, staff) print('工资大于4000的员工:', list(lst_salary)) ''' 4.max 和 min''' # 计算最大工资的员工 print('最高工资的员工:', max(staff, key=lambda x: x['salary'])) # 计算最小年龄的员工 print('最低工资的员工:', min(staff, key=lambda x: x['age'])) ''' 5.sorted把一个迭代对象里的每个元素做排序,最终返回一个列表''' # 根据员工年龄降序排序 list_sorted = sorted(staff, key=lambda x: x['age'], reverse=True) print('工资降序排序:', list_sorted)
4.map
函数
map()
函数,把一个可迭代对象中的每一个元素换成一个新的对象,最终返回一个迭代器
。
Python内置map()
函数:
class map(object): """ map(func, *iterables) --> map object Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted. """ def __getattribute__(self, *args, **kwargs): # real signature unknown """ Return getattr(self, name). """ pass def __init__(self, func, *iterables): # real signature unknown; restored from __doc__ pass def __iter__(self, *args, **kwargs): # real signature unknown """ Implement iter(self). """ pass @staticmethod # known case of __new__ def __new__(*args, **kwargs): # real signature unknown """ Create and return a new object. See help(type) for accurate signature. """ pass def __next__(self, *args, **kwargs): # real signature unknown """ Implement next(self). """ pass def __reduce__(self, *args, **kwargs): # real signature unknown """ Return state information for pickling. """ pass
map()
函数的返回值:
map(func, *iterables) --> map object
参数详解:
""" func:代表传入参数为函数,这里的函数指定指向函数的函数名 *iterables:代表参数指定的可迭代的 返回值:返回处理好的数据 map()函数:是将传入的func函数作用于可迭代的数据里的面每个元素,并将处理好的新的结果返回 """
代码实现
# -*- coding: utf-8 -*- # @File : map函数.py # @author: Flyme awei # @email : Flymeawei@163.com # @Time : 2022/8/21 10:03 lst = [1, 2, 3, 4, 5] ite = map(lambda x: x**2, lst) print(ite) # for i in ite: print(i, end=' ')
5.聚合函数reduce
reduce()
函数,把一个可迭代对象中的每个元素做聚合处理,最终返回一个聚合之后的值.
functools
函数reduce()
def reduce(function, sequence, initial=_initial_missing): """ reduce(function, sequence[, initial]) -> value Apply a function of two arguments cumulatively to the items of a sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). If initial is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. """ it = iter(sequence) if initial is _initial_missing: try: value = next(it) except StopIteration: raise TypeError("reduce() of empty sequence with no initial value") from None else: value = initial for element in it: value = function(value, element) return value try: from _functools import reduce except ImportError: pass
reduce
函数的参数与返回值:
注意使用reduce
函数时需要先导入,reduce
函数是在 functools
模块里面
from functools import reduce reduce(function, sequence[, initial]) -> value # 参数详解 """ function:一个有两个参数的函数 sequence:是一个序列,是一些数据的集合,或者是一组数据,可迭代对象 initial:可选,初始参数 返回值:返回函数计算的结果 reduce()函数,使用function函数(有两个参数)先对集合中的sequence第 1、2 个元素进行操作,如果存在 initial参数,则将会以sequence中的第一个元素和initial作为参数,用作调用,得到的结果再与sequence中的 下一个数据用 function 函数运算,最后得到一个结果。 """
代码实现:
# -*- coding: utf-8 -*- # @File : 聚合函数reduce.py # @author: Flyme awei # @email : Flymeawei@163.com # @Time : 2022/8/21 12:48 from functools import reduce lst = [1, 2, 3, 4, 5] va = reduce(lambda x, y: x+y, lst) # 求累加 print('s =', va) def max_(x, y): if x > y: return x max1 = reduce(max_, iter((3, 2))) # 比较大小求大值 print(f'max = {max1}')
6.过滤器filter
函数
filter()
函数 把一个可迭代对象中的元素做过滤操作,如果func
返回值为True
则留下,否则过滤掉。
Python内置的 filter()
函数用于过滤序列,和 map()
类似, filter()
也接收一个函数和一个序列,但是不同的是 filter()
把传入的函数依次作用于每个元素,然后根据返回值是 True
还是 False
决定元素的保留与丢弃。
Python内置函数filter()
class filter(object): """ filter(function or None, iterable) --> filter object Return an iterator yielding those items of iterable for which function(item) is true. If function is None, return the items that are true. """ def __getattribute__(self, *args, **kwargs): # real signature unknown """ Return getattr(self, name). """ pass def __init__(self, function_or_None, iterable): # real signature unknown; restored from __doc__ pass def __iter__(self, *args, **kwargs): # real signature unknown """ Implement iter(self). """ pass @staticmethod # known case of __new__ def __new__(*args, **kwargs): # real signature unknown """ Create and return a new object. See help(type) for accurate signature. """ pass def __next__(self, *args, **kwargs): # real signature unknown """ Implement next(self). """ pass def __reduce__(self, *args, **kwargs): # real signature unknown """ Return state information for pickling. """ pass
参数列表:
filter(function, iterable) """ function:判断函数。 iterable:序列,(可迭代对象)。 返回值:返回列表 filter函数,序列(可迭代对象)的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返 回 True 的元素放到新列表中 """
filter
函数实现过滤奇数:
# -*- coding: utf-8 -*- # @File : filter函数.py # @author: Flyme awei # @email : Flymeawei@163.com # @Time : 2022/8/21 13:06 def not_odd(num): return num % 2 == 0 # 过滤奇数 new_lst = filter(not_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) print(list(new_lst))
这里定义了一个函数not_odd
,不是奇数的函数,这个函数,只有当参数为2的整数倍时返回True
。
这里filter
函数的两个参数第一个是过滤方法,第二个是需要过滤的列表,将列表里面的元素依次带入函数中进行运算,得到的结果如果为True
时,将此结果作为新的filter
对象保留,等待函数里面的列表执行完成后,返回最终的值,这里的值为列表
,也就是过滤掉了False
的数据或元素。
filter
函数过滤操作
# -*- coding: utf-8 -*- # @File : filter函数.py # @author: Flyme awei # @email : Flymeawei@163.com # @Time : 2022/8/21 13:06 # filter 把一个可迭代对象中的元素做过滤操作,若果func返回值为True是留下,否则过滤掉 staff = [ {'name': '张三', 'age': 18, 'salary': 2000}, {'name': '李四', 'age': 20, 'salary': 4000}, {'name': '麻子', 'age': 22, 'salary': 6000}] # 过滤留下大于18岁的员工 lst_age = filter(lambda x: x['age'] > 18, staff) print(list(lst_age)) # 过滤留下工资大于4000的员工 lst_salary = filter(lambda x: x['salary'] > 4000, staff) print(list(lst_salary))
作者:北极的三哈 来源:稀土掘金