Python高阶函数及常用的内置高阶函数(map、filter、reduce)

高阶函数是指可以接收另一个函数作为参数的函数。它是函数式编程的体现。

函数式编程减少了代码的重复,所有程序比较短,提高了开发速度。

比如说:将任意两个数按要求处理后再进行求和。

def fun_add(a,b):
    return abs(a) + abs(b)

result = fun_add(-10,20)
print(result)   # 30

上面这个 fun_add() 函数是将两个数取绝对值后再进行求和的。如果我们想要将两个数进行四舍五入后再求和的话,就需要修改代码或者重新编写一个求和函数。这就比较麻烦了。而如果使用高阶函数,代码就会很简单了。

那么什么是高阶函数呢?怎么使用高阶函数去解决这个问题呢?

体验什么是高阶函数?

首先我们知道在 Python 中一切皆对象,所以函数也是对象。如果使用一个变量指向某一个函数,那么调用这个变量和调用这个函数的效果是一样的,所以变量可以指向函数

>>> abs(-11)   # 调用函数abs
11
>>> f = abs    # 变量f指向函数abs
>>> f(-11)     # 调用这个变量
11
>>> abs
<built-in function abs>
>>> f
<built-in function abs>

从上面结果可以看出,变量 f 可以指向函数 abs,且调用 f 这个变量 (f(x))和调用 abs 函数(abs()),它们得到的结果是一样的。

同理:函数名也是指向函数的变量。例如 abs 函数本来是求绝对值的,我们将 abs 指向另一个函数 round ,然后去调用他们,看会出现什么样的结果:

>>> abs     # 这里abs函数还是求绝对值的
<built-in function abs>
>>> abs = round   # abs指向round函数
>>> abs     # abs这里变成了用于取四舍五入值的函数了
<built-in function round>
>>> round
<built-in function round>
>>> round(1.2)
1
>>> abs(1.2)
1

从上面结果可以看出,abs 指向 round 函数后,调用 abs() 得到的结果和调用 round() 得到的结果是一样的。所以这说明函数名也是指向函数的变量。

补充:

abs(x):返回x的绝对值。

round(x):返回x的四舍五入后的值。

综合上面的例子可以看出:变量可以指向一个函数,且函数名是指向函数的变量。而调用函数时,可以接收一个变量来作为参数,这也就是说一个函数可以当做参数传给另一个函数

这时我们再去考虑使用高阶函数去解决上面那个问题:将任意两个数按要求处理后再进行求和。

首先我们给求和函数定义三个参数,最后一个参数用于接收处理数字的函数(这个函数可以是自定义的,也可以是 Python 内置函数),我们在调用它的时候,将处理数字的函数当做参数传进去。

def fun(x):
    return x*2

def fun_add(a,b,f):    # a,b是用于求和的两个数字。f是一个函数
    return f(a)+f(b)   # 把a、b放到f函数中处理,然后求和

# 作为参数的函数可以是自定义的,也可以是内置的

# 将fun作为参数传进去,即:将两个数都乘2,再求和
print(fun_add(8,10,fun))    # 36

# 将两个数取绝对值再求和
print(fun_add(8,-10,abs))   # 18

# 将两个数四舍五入再求和
print(fun_add(1.2,3.8,round))    # 5


def fun_add1(a,b,f,g):
    return f(a)+g(b)

print(fun_add1(-20,8.8,abs,round))  # 29

上面的 fun_add 就是一个高阶函数。

综合上面处理这个问题的两种方式可以看出:使用高阶函数的话只需要写一个函数就可以完成多种处理数据的情况,如果不使用高阶函数,则需要处理一种数据定义一个函数,或者修改代码。

Python 常用内置高阶函数

1、map()

语法格式:
map(function,iterable,...)
参数说明:

function:用于处理 iterable 序列中元素的函数。

iterable:可迭代序列(如列表、字符串等),可以是多个。

函数描述:

将 iterable 中的每一个元素作为参数传给 faction 函数去加工,然后返回所有加工完成的数据组成的列表。(python 3.x 返回的是迭代器对象,python 2.x 返回的是列表)

简单说就是将 iterable 中的值排好队,然后挨个进入 faction 中处理,处理好的数据再挨个存入列表中。

例如:将 [1,3,5,7,9] 列表中的每一个元素都取 2 次幂。

lst = [1,3,5,7,9]

def fun(a):
    return a**2

# 将lst中的每个元素都当做参数传入fun函数中进行处理,得到一个新的列表将其返回
result = map(fun,lst)

# 得到的结果是<class 'map'>类型的对象,可以通过list()将其转换成列表输出
print(list(result)) # [1, 9, 25, 49, 81]

输出结果:[1, 9, 25, 49, 81]

图片[1]-Python高阶函数及常用的内置高阶函数(map、filter、reduce)-尤尤'blog

使用 lambda 表达式简化上面的代码:

lst = [1,3,5,7,9]

r = map(lambda x:x**2,lst)
print(list(r))  # [1, 9, 25, 49, 81]

输出结果:[1, 9, 25, 49, 81]

2、filter()

语法格式:
filter(function,iterable)
参数说明:

function:判断函数,判断函数的返回值是布尔类型。这个参数可以是 None。

iterable:可迭代对象。

返回值:

返回的是一个迭代器对象,要查看值,可以使用 list() 转换成列表。

函数描述:

filter() 函数用于过滤序列,将不符合要求的元素过滤掉。

如果第一个参数是函数的话,就把 iterable 序列中的每一个元素作为参数,传递给函数来判断是否符合条件,将返回 True 的值筛选出来组成一个列表返回

如果第一个参数是 None 的话,就把 iterable 中为 True 的值组成一个列表返回。

实例1:将序列中的偶数筛选出来,也就是过滤掉奇数。

def even(x):
    return x%2 == 0    # 偶数和2的余数是0,0==0结果为True

result = filter(even,range(11))
print(list(result))     # [0, 2, 4, 6, 8, 10]

输出结果:[0, 2, 4, 6, 8, 10]

使用 lambda 表达式:

lst = filter(lambda x:x%2==0,range(11))
print(list(lst))  

输出结果:[0, 2, 4, 6, 8, 10]

如果 filter() 的第一个代表函数的参数是 None,则将可迭代序列中值为 True 的元素组成一个列表返回。

lst = [10,'hello','',False,None,213,[],12]

result = filter(None,lst)

print(list(result))

输出结果:[10, ‘hello’, 213, 12]

实例2:过滤掉空字符串。

图片[2]-Python高阶函数及常用的内置高阶函数(map、filter、reduce)-尤尤'blog

如果像上面这样写的话,要是过滤的列表中有 None ,程序就会抛出异常 AttributeError,告诉我们 None 没有 strip() 方法。

要想解决这个问题,可以改成 “return s and len(s.strip()) > 0” ,利用布尔运算的短路原则(and:有一个为 False,结果就为 False),None 的布尔值是 False,这样就可以去除 None了。

def is_not_empty(s):
    return s and len(s.strip()) > 0    # 1个空字符的长度为1,所以要去掉开头和结尾的空白字符串

lst = ['hello','   ','  world',None]
result = filter(is_not_empty,lst)
print(list(result))

返回结果:[‘hello’, ‘ world’]

3、reduce()

语法格式:
reduce(function,iterable)
参数说明:

function:函数,他必须要有两个参数,因为每次 function 计算的结果要继续和 iterable 的下一个元素做累积计算。

iterable:可迭代序列。

返回值:

返回函数计算的结果。

函数描述:

使用 reduce 的第一个参数函数 function 先对序列 iterable 中的第 1、2 个元素进行操作,然后将得到的结果与和 iterable 中的第三个数据传入 function 中进行操作,以此类推,最后返回一个值

from functools import reduce

def fun(x,y):
    return x*y

result = reduce(fun,range(1,6))  # 1*2*3*4*5
print(result)

输出结果:120

结合 lambda 表达式来完成上面操作:

result = reduce(lambda x,y: x*y,range(1,6))
print(result)

输出结果:120

注意:在 python 3.x 中,reduce() 被移到了 functools 模块中,要使用它,需要导入 functools 模块,然后调用 reduce() 函数

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容